1 |
00947987
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
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.objectlib.tablebases;
|
11 |
|
|
|
12 |
3103c3c8
|
Leszek Koltunski
|
import org.distorted.objectlib.helpers.OperatingSystemInterface;
|
13 |
00947987
|
Leszek Koltunski
|
|
14 |
884b702b
|
Leszek Koltunski
|
import java.io.ByteArrayOutputStream;
|
15 |
|
|
import java.io.IOException;
|
16 |
|
|
import java.io.InputStream;
|
17 |
00947987
|
Leszek Koltunski
|
|
18 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
19 |
|
|
|
20 |
f079bf77
|
Leszek Koltunski
|
public abstract class TablebasesPruning extends TablebasesAbstract
|
21 |
884b702b
|
Leszek Koltunski
|
{
|
22 |
bdcb662f
|
Leszek Koltunski
|
private final int mGodsNumber;
|
23 |
|
|
|
24 |
f079bf77
|
Leszek Koltunski
|
private PruningTable[] mHighTables;
|
25 |
|
|
private PruningTable[] mMidTables;
|
26 |
3feba94e
|
Leszek Koltunski
|
private int mLowestHigh, mHighestMid, mLowestMid;
|
27 |
00947987
|
Leszek Koltunski
|
|
28 |
15d1f6ad
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
29 |
|
|
|
30 |
f079bf77
|
Leszek Koltunski
|
abstract int[] getMidPruningLevels();
|
31 |
|
|
abstract int[] getHighPruningLevels();
|
32 |
|
|
abstract int getGodsNumber();
|
33 |
bdcb662f
|
Leszek Koltunski
|
abstract boolean moveCanProceed(int lastA, int lastL, int currA, int currL);
|
34 |
15d1f6ad
|
Leszek Koltunski
|
|
35 |
00947987
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
36 |
|
|
|
37 |
3103c3c8
|
Leszek Koltunski
|
private PruningTable createPruningTable(OperatingSystemInterface os, int id)
|
38 |
00947987
|
Leszek Koltunski
|
{
|
39 |
3103c3c8
|
Leszek Koltunski
|
InputStream stream = os.openLocalFile(id);
|
40 |
884b702b
|
Leszek Koltunski
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
41 |
00947987
|
Leszek Koltunski
|
|
42 |
884b702b
|
Leszek Koltunski
|
int nRead;
|
43 |
|
|
byte[] tmp = new byte[16384];
|
44 |
00947987
|
Leszek Koltunski
|
|
45 |
884b702b
|
Leszek Koltunski
|
try
|
46 |
00947987
|
Leszek Koltunski
|
{
|
47 |
884b702b
|
Leszek Koltunski
|
while ((nRead = stream.read(tmp, 0, tmp.length)) != -1)
|
48 |
00947987
|
Leszek Koltunski
|
{
|
49 |
884b702b
|
Leszek Koltunski
|
buffer.write(tmp, 0, nRead);
|
50 |
00947987
|
Leszek Koltunski
|
}
|
51 |
884b702b
|
Leszek Koltunski
|
stream.close();
|
52 |
|
|
byte[] data = buffer.toByteArray();
|
53 |
|
|
buffer.close();
|
54 |
f079bf77
|
Leszek Koltunski
|
return new PruningTable(data);
|
55 |
884b702b
|
Leszek Koltunski
|
}
|
56 |
|
|
catch(IOException ex)
|
57 |
00947987
|
Leszek Koltunski
|
{
|
58 |
884b702b
|
Leszek Koltunski
|
mInitialized = false;
|
59 |
f079bf77
|
Leszek Koltunski
|
return null;
|
60 |
00947987
|
Leszek Koltunski
|
}
|
61 |
884b702b
|
Leszek Koltunski
|
}
|
62 |
00947987
|
Leszek Koltunski
|
|
63 |
884b702b
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
64 |
00947987
|
Leszek Koltunski
|
|
65 |
f079bf77
|
Leszek Koltunski
|
public TablebasesPruning()
|
66 |
884b702b
|
Leszek Koltunski
|
{
|
67 |
|
|
super();
|
68 |
f079bf77
|
Leszek Koltunski
|
mGodsNumber = getGodsNumber();
|
69 |
7363eaa6
|
Leszek Koltunski
|
mInitialized = false;
|
70 |
00947987
|
Leszek Koltunski
|
}
|
71 |
|
|
|
72 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
73 |
|
|
|
74 |
3103c3c8
|
Leszek Koltunski
|
public TablebasesPruning(OperatingSystemInterface os, int[] midIDs, int[] highIDs)
|
75 |
00947987
|
Leszek Koltunski
|
{
|
76 |
884b702b
|
Leszek Koltunski
|
super();
|
77 |
|
|
|
78 |
f079bf77
|
Leszek Koltunski
|
int mid = midIDs !=null ? midIDs.length : 0;
|
79 |
|
|
int high= highIDs!=null ? highIDs.length : 0;
|
80 |
|
|
|
81 |
|
|
mMidTables = mid >0 ? new PruningTable[mid] : null;
|
82 |
|
|
mHighTables= high>0 ? new PruningTable[high]: null;
|
83 |
|
|
mGodsNumber = getGodsNumber();
|
84 |
884b702b
|
Leszek Koltunski
|
mInitialized = true;
|
85 |
|
|
|
86 |
3103c3c8
|
Leszek Koltunski
|
for(int i=0; i<mid ; i++) mMidTables[i] = createPruningTable(os,midIDs[i] );
|
87 |
|
|
for(int i=0; i<high; i++) mHighTables[i]= createPruningTable(os,highIDs[i]);
|
88 |
bdcb662f
|
Leszek Koltunski
|
|
89 |
|
|
computeLowHigh();
|
90 |
00947987
|
Leszek Koltunski
|
}
|
91 |
|
|
|
92 |
15d1f6ad
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
93 |
|
|
|
94 |
|
|
public byte[][] getPacked()
|
95 |
|
|
{
|
96 |
7363eaa6
|
Leszek Koltunski
|
if( !mInitialized )
|
97 |
|
|
{
|
98 |
f079bf77
|
Leszek Koltunski
|
int[] midLevels = getMidPruningLevels();
|
99 |
|
|
int numMidLevels= midLevels!=null ? midLevels.length : 0;
|
100 |
|
|
int[] highLevels = getHighPruningLevels();
|
101 |
|
|
int numHighLevels= highLevels!=null ? highLevels.length : 0;
|
102 |
7363eaa6
|
Leszek Koltunski
|
int maxLevel = 0;
|
103 |
15d1f6ad
|
Leszek Koltunski
|
|
104 |
f079bf77
|
Leszek Koltunski
|
if( highLevels!=null )
|
105 |
|
|
{
|
106 |
|
|
for( int l : highLevels )
|
107 |
|
|
if( l>maxLevel ) maxLevel = l;
|
108 |
|
|
}
|
109 |
|
|
else
|
110 |
|
|
{
|
111 |
|
|
if( midLevels!=null )
|
112 |
|
|
for( int l : midLevels )
|
113 |
|
|
if( l>maxLevel ) maxLevel = l;
|
114 |
|
|
}
|
115 |
15d1f6ad
|
Leszek Koltunski
|
|
116 |
7363eaa6
|
Leszek Koltunski
|
createTablebase(maxLevel);
|
117 |
f079bf77
|
Leszek Koltunski
|
mMidTables = numMidLevels >0 ? new PruningTable[numMidLevels ] : null;
|
118 |
|
|
mHighTables= numHighLevels>0 ? new PruningTable[numHighLevels] : null;
|
119 |
15d1f6ad
|
Leszek Koltunski
|
|
120 |
f079bf77
|
Leszek Koltunski
|
for(int i=0; i<numMidLevels; i++)
|
121 |
|
|
mMidTables[i] = new PruningTable(mTablebase,midLevels[i]);
|
122 |
|
|
for(int i=0; i<numHighLevels; i++)
|
123 |
|
|
mHighTables[i] = new PruningTable(mTablebase,highLevels[i]);
|
124 |
15d1f6ad
|
Leszek Koltunski
|
|
125 |
bdcb662f
|
Leszek Koltunski
|
computeLowHigh();
|
126 |
|
|
|
127 |
7363eaa6
|
Leszek Koltunski
|
mInitialized = true;
|
128 |
15d1f6ad
|
Leszek Koltunski
|
}
|
129 |
|
|
|
130 |
f079bf77
|
Leszek Koltunski
|
int midNum = mMidTables !=null ? mMidTables.length : 0;
|
131 |
|
|
int highNum = mHighTables!=null ? mHighTables.length : 0;
|
132 |
|
|
byte[][] data = new byte[midNum+highNum][];
|
133 |
|
|
|
134 |
|
|
for(int i=0; i<midNum ; i++) data[i ] = mMidTables[i].getPacked();
|
135 |
|
|
for(int i=0; i<highNum; i++) data[i+midNum] = mHighTables[i].getPacked();
|
136 |
7363eaa6
|
Leszek Koltunski
|
|
137 |
15d1f6ad
|
Leszek Koltunski
|
return data;
|
138 |
|
|
}
|
139 |
|
|
|
140 |
00947987
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
141 |
|
|
|
142 |
bdcb662f
|
Leszek Koltunski
|
private void computeLowHigh()
|
143 |
|
|
{
|
144 |
|
|
mLowestHigh = mGodsNumber+1;
|
145 |
|
|
int numHigh = mHighTables==null ? 0 : mHighTables.length;
|
146 |
|
|
|
147 |
|
|
for( int i=0; i<numHigh; i++ )
|
148 |
|
|
{
|
149 |
|
|
int level = mHighTables[i].getLevel();
|
150 |
|
|
if( i==0 || level<mLowestHigh ) mLowestHigh=level;
|
151 |
|
|
}
|
152 |
|
|
|
153 |
|
|
mLowestMid = 0;
|
154 |
|
|
mHighestMid= 0;
|
155 |
|
|
int numMid = mMidTables==null ? 0 : mMidTables.length;
|
156 |
|
|
|
157 |
|
|
for( int i=0; i<numMid; i++ )
|
158 |
|
|
{
|
159 |
|
|
int level = mMidTables[i].getLevel();
|
160 |
|
|
if( i==0 || level<mLowestMid ) mLowestMid =level;
|
161 |
|
|
if( i==0 || level>mHighestMid ) mHighestMid=level;
|
162 |
|
|
}
|
163 |
|
|
}
|
164 |
|
|
|
165 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
166 |
|
|
|
167 |
|
|
public int traverseDownTable(int index, PruningTable[] tables, int tableIndex, int lastA, int lastR, int[] move, int[] tmpQuats)
|
168 |
|
|
{
|
169 |
|
|
int[] quats = getQuats(index);
|
170 |
|
|
int numQuats = quats.length;
|
171 |
|
|
|
172 |
|
|
move[0]=0;
|
173 |
|
|
move[1]=0;
|
174 |
|
|
move[2]=1;
|
175 |
|
|
move[3]=1;
|
176 |
|
|
|
177 |
693cc52e
|
Leszek Koltunski
|
for(int cubit=0; cubit<mNumCubits; cubit++) mRotRow[cubit] = computeRow(cubit,quats[cubit]);
|
178 |
bdcb662f
|
Leszek Koltunski
|
|
179 |
|
|
for(int s=0; s<mScalingFactor; s++)
|
180 |
|
|
{
|
181 |
|
|
int ax = move[0];
|
182 |
|
|
int layer = move[1];
|
183 |
|
|
int quat = move[3];
|
184 |
|
|
|
185 |
|
|
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) )
|
186 |
|
|
{
|
187 |
3feba94e
|
Leszek Koltunski
|
int bitLayer = computeBitLayer(ax,layer);
|
188 |
bdcb662f
|
Leszek Koltunski
|
System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
|
189 |
|
|
|
190 |
|
|
for(int cubit=0; cubit<mNumCubits; cubit++)
|
191 |
3feba94e
|
Leszek Koltunski
|
if( (mRotRow[cubit][ax] & bitLayer) != 0 )
|
192 |
bdcb662f
|
Leszek Koltunski
|
{
|
193 |
|
|
int currQuat = tmpQuats[cubit];
|
194 |
|
|
int newQuat = getMultQuat(quat,currQuat);
|
195 |
|
|
tmpQuats[cubit] = newQuat;
|
196 |
|
|
}
|
197 |
|
|
|
198 |
|
|
int childIndex = getIndex(tmpQuats);
|
199 |
|
|
|
200 |
|
|
if( tableIndex>0 )
|
201 |
|
|
{
|
202 |
|
|
if( tables[tableIndex-1].contains(childIndex) ) return childIndex;
|
203 |
|
|
}
|
204 |
|
|
else if( !tables[0].contains(childIndex) )
|
205 |
|
|
{
|
206 |
|
|
if( tables.length<=1 || !tables[1].contains(childIndex) ) return childIndex;
|
207 |
|
|
}
|
208 |
|
|
}
|
209 |
|
|
|
210 |
|
|
getNextAxisLayerAngleQuat(move);
|
211 |
|
|
}
|
212 |
|
|
|
213 |
|
|
return -1;
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
217 |
|
|
|
218 |
|
|
private int traversePruningBlock(int[][] moves, PruningTable[] tables, int tableIndex, int index, int lastA, int lastR)
|
219 |
00947987
|
Leszek Koltunski
|
{
|
220 |
bdcb662f
|
Leszek Koltunski
|
int movesIndex = 1;
|
221 |
aa0757b6
|
Leszek Koltunski
|
int[] move, tmpQuats = new int[mNumCubits];
|
222 |
bdcb662f
|
Leszek Koltunski
|
|
223 |
|
|
do
|
224 |
|
|
{
|
225 |
aa0757b6
|
Leszek Koltunski
|
move = moves[movesIndex++];
|
226 |
bdcb662f
|
Leszek Koltunski
|
index = traverseDownTable(index,tables,tableIndex,lastA,lastR,move,tmpQuats);
|
227 |
|
|
lastA = move[0];
|
228 |
|
|
lastR = move[1];
|
229 |
|
|
tableIndex--;
|
230 |
|
|
}
|
231 |
|
|
while( tableIndex>=0 );
|
232 |
|
|
|
233 |
|
|
return index;
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
237 |
|
|
// ret: [0][] --> (new index,new depth,?,?) ; [1...N-1][] --> moves. (or null if index not in High)
|
238 |
|
|
|
239 |
|
|
private int[][] traverseBlock(int index, PruningTable[] tables, int lastA, int lastR)
|
240 |
|
|
{
|
241 |
|
|
int num = (tables==null) ? 0 : tables.length;
|
242 |
|
|
int tableIndex = -1;
|
243 |
|
|
|
244 |
|
|
for( int i=0; i<num; i++ )
|
245 |
|
|
if( tables[i].contains(index) )
|
246 |
|
|
{
|
247 |
|
|
tableIndex = i;
|
248 |
|
|
break;
|
249 |
|
|
}
|
250 |
|
|
|
251 |
b9633e5f
|
Leszek Koltunski
|
if( tableIndex<0 ) return null;
|
252 |
bdcb662f
|
Leszek Koltunski
|
|
253 |
|
|
int[][] ret = new int[tableIndex+2][4];
|
254 |
|
|
ret[0][1] = tables[0].getLevel()-1;
|
255 |
|
|
ret[0][0] = traversePruningBlock(ret,tables,tableIndex,index,lastA, lastR);
|
256 |
|
|
|
257 |
|
|
return ret;
|
258 |
|
|
}
|
259 |
|
|
|
260 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
261 |
|
|
|
262 |
|
|
private int midTablesContain(int index)
|
263 |
|
|
{
|
264 |
|
|
int num = mMidTables.length;
|
265 |
|
|
|
266 |
|
|
for( int i=0; i<num; i++ )
|
267 |
|
|
if( mMidTables[i].contains(index) )
|
268 |
|
|
return i;
|
269 |
|
|
|
270 |
|
|
return -1;
|
271 |
|
|
}
|
272 |
|
|
|
273 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
274 |
|
|
|
275 |
f51c164f
|
Leszek Koltunski
|
private boolean jumpMidSolvedRecursive(int[] quats, int jump, int depth, int lastA, int lastR,
|
276 |
|
|
int[][] solution, int[][] tmpE, int[][][] rotRowE )
|
277 |
bdcb662f
|
Leszek Koltunski
|
{
|
278 |
aa0757b6
|
Leszek Koltunski
|
int numQuats = quats.length;
|
279 |
|
|
int[] move = solution[depth];
|
280 |
f51c164f
|
Leszek Koltunski
|
int[] tmp = tmpE[jump];
|
281 |
|
|
int[][] rotRow= rotRowE[jump];
|
282 |
bdcb662f
|
Leszek Koltunski
|
|
283 |
|
|
move[0]=0;
|
284 |
|
|
move[1]=0;
|
285 |
|
|
move[2]=1;
|
286 |
|
|
move[3]=1;
|
287 |
|
|
|
288 |
693cc52e
|
Leszek Koltunski
|
for(int cubit=0; cubit<mNumCubits; cubit++) rotRow[cubit] = computeRow(cubit,quats[cubit]);
|
289 |
bdcb662f
|
Leszek Koltunski
|
|
290 |
|
|
for(int s=0; s<mScalingFactor; s++)
|
291 |
|
|
{
|
292 |
|
|
int ax = move[0];
|
293 |
|
|
int layer = move[1];
|
294 |
|
|
int quat = move[3];
|
295 |
|
|
|
296 |
|
|
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,ax,layer) )
|
297 |
|
|
{
|
298 |
3feba94e
|
Leszek Koltunski
|
int bitLayer = computeBitLayer(ax,layer);
|
299 |
bdcb662f
|
Leszek Koltunski
|
System.arraycopy(quats, 0, tmp, 0, numQuats);
|
300 |
|
|
|
301 |
|
|
for(int cubit=0; cubit<mNumCubits; cubit++)
|
302 |
3feba94e
|
Leszek Koltunski
|
if( (rotRow[cubit][ax] & bitLayer) != 0 )
|
303 |
693cc52e
|
Leszek Koltunski
|
tmp[cubit] = getMultQuat(quat,tmp[cubit]);
|
304 |
bdcb662f
|
Leszek Koltunski
|
|
305 |
|
|
int childIndex = getIndex(tmp);
|
306 |
|
|
|
307 |
5b9f1cec
|
Leszek Koltunski
|
if( isSolved(childIndex) )
|
308 |
bdcb662f
|
Leszek Koltunski
|
{
|
309 |
|
|
solution[0][0] = childIndex;
|
310 |
|
|
solution[0][1] = 0;
|
311 |
|
|
return true;
|
312 |
|
|
}
|
313 |
|
|
|
314 |
|
|
int containingTable = midTablesContain(childIndex);
|
315 |
|
|
|
316 |
|
|
if( containingTable>=0 )
|
317 |
|
|
{
|
318 |
|
|
solution[0][0] = childIndex;
|
319 |
|
|
solution[0][1] = mMidTables[containingTable].getLevel();
|
320 |
|
|
return true;
|
321 |
|
|
}
|
322 |
|
|
|
323 |
f51c164f
|
Leszek Koltunski
|
if( jump>1 && jumpMidSolvedRecursive(tmp, jump-1, depth+1, ax, layer, solution, tmpE, rotRowE) )
|
324 |
bdcb662f
|
Leszek Koltunski
|
{
|
325 |
|
|
return true;
|
326 |
|
|
}
|
327 |
|
|
}
|
328 |
|
|
|
329 |
|
|
getNextAxisLayerAngleQuat(move);
|
330 |
|
|
}
|
331 |
|
|
|
332 |
|
|
return false;
|
333 |
|
|
}
|
334 |
|
|
|
335 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
336 |
cd595931
|
Leszek Koltunski
|
// ret: [0][] --> (new index,new depth,num moves,?) ; [1...N-1][] --> moves.
|
337 |
bdcb662f
|
Leszek Koltunski
|
|
338 |
5b9d6595
|
Leszek Koltunski
|
private int[][] jumpToMidOrSolved(int index, int maxJump, int lastA, int lastR)
|
339 |
bdcb662f
|
Leszek Koltunski
|
{
|
340 |
aa0757b6
|
Leszek Koltunski
|
if( midTablesContain(index)>=0 ) return null;
|
341 |
|
|
|
342 |
bdcb662f
|
Leszek Koltunski
|
int[][] solution = new int[maxJump+1][4];
|
343 |
ca2ba7a1
|
Leszek Koltunski
|
int[] quats = getQuats(index);
|
344 |
bdcb662f
|
Leszek Koltunski
|
|
345 |
f51c164f
|
Leszek Koltunski
|
int[][] tmpE = new int[maxJump+1][mNumCubits];
|
346 |
|
|
int[][][] rotRowE = new int[maxJump+1][mNumCubits][mNumAxis];
|
347 |
|
|
|
348 |
b9633e5f
|
Leszek Koltunski
|
for(int i=1; i<=maxJump; i++)
|
349 |
f51c164f
|
Leszek Koltunski
|
if( jumpMidSolvedRecursive(quats,i,1,lastA,lastR,solution,tmpE,rotRowE) )
|
350 |
aa0757b6
|
Leszek Koltunski
|
{
|
351 |
cd595931
|
Leszek Koltunski
|
solution[0][2] = i;
|
352 |
bdcb662f
|
Leszek Koltunski
|
return solution;
|
353 |
aa0757b6
|
Leszek Koltunski
|
}
|
354 |
bdcb662f
|
Leszek Koltunski
|
|
355 |
|
|
return null;
|
356 |
|
|
}
|
357 |
|
|
|
358 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
359 |
|
|
|
360 |
ca2ba7a1
|
Leszek Koltunski
|
private boolean jumpToSolvedRecursive(int[] quats, int jump, int depth, int lastA, int lastR, int[][] solution)
|
361 |
bdcb662f
|
Leszek Koltunski
|
{
|
362 |
|
|
int numQuats = quats.length;
|
363 |
|
|
int[] move = solution[depth];
|
364 |
|
|
int[] tmp = new int[mNumCubits];
|
365 |
aa0757b6
|
Leszek Koltunski
|
int[][]rotRow= new int[mNumCubits][mNumAxis];
|
366 |
bdcb662f
|
Leszek Koltunski
|
|
367 |
|
|
move[0]=0;
|
368 |
|
|
move[1]=0;
|
369 |
|
|
move[2]=1;
|
370 |
|
|
move[3]=1;
|
371 |
|
|
|
372 |
693cc52e
|
Leszek Koltunski
|
for(int cubit=0; cubit<mNumCubits; cubit++) rotRow[cubit] = computeRow(cubit,quats[cubit]);
|
373 |
bdcb662f
|
Leszek Koltunski
|
|
374 |
|
|
for(int s=0; s<mScalingFactor; s++)
|
375 |
|
|
{
|
376 |
|
|
int ax = move[0];
|
377 |
|
|
int layer = move[1];
|
378 |
|
|
int quat = move[3];
|
379 |
|
|
|
380 |
|
|
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) )
|
381 |
|
|
{
|
382 |
3feba94e
|
Leszek Koltunski
|
int bitLayer = computeBitLayer(ax,layer);
|
383 |
bdcb662f
|
Leszek Koltunski
|
System.arraycopy(quats, 0, tmp, 0, numQuats);
|
384 |
|
|
|
385 |
|
|
for(int cubit=0; cubit<mNumCubits; cubit++)
|
386 |
3feba94e
|
Leszek Koltunski
|
if( (rotRow[cubit][ax] & bitLayer) != 0 )
|
387 |
bdcb662f
|
Leszek Koltunski
|
{
|
388 |
|
|
int currQuat = tmp[cubit];
|
389 |
|
|
int newQuat = getMultQuat(quat,currQuat);
|
390 |
|
|
tmp[cubit] = newQuat;
|
391 |
|
|
}
|
392 |
|
|
|
393 |
|
|
int childIndex = getIndex(tmp);
|
394 |
5b9d6595
|
Leszek Koltunski
|
if( isSolved(childIndex) ) return true;
|
395 |
ca2ba7a1
|
Leszek Koltunski
|
if( jump>1 && jumpToSolvedRecursive(tmp, jump-1, depth+1, ax, layer, solution) ) return true;
|
396 |
bdcb662f
|
Leszek Koltunski
|
}
|
397 |
|
|
|
398 |
|
|
getNextAxisLayerAngleQuat(move);
|
399 |
|
|
}
|
400 |
|
|
|
401 |
|
|
return false;
|
402 |
|
|
}
|
403 |
|
|
|
404 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
405 |
aa0757b6
|
Leszek Koltunski
|
// ret: [0][] --> (numMoves,old depth,?,?) ; [1...N-1][] --> moves.
|
406 |
bdcb662f
|
Leszek Koltunski
|
|
407 |
5b9d6595
|
Leszek Koltunski
|
private int[][] jumpToSolved(int index, int maxJump, int lastA, int lastR)
|
408 |
bdcb662f
|
Leszek Koltunski
|
{
|
409 |
|
|
int[][] solution = new int[maxJump+1][4];
|
410 |
ca2ba7a1
|
Leszek Koltunski
|
int[] quats = getQuats(index);
|
411 |
bdcb662f
|
Leszek Koltunski
|
|
412 |
b9633e5f
|
Leszek Koltunski
|
for(int i=1; i<=maxJump; i++)
|
413 |
ca2ba7a1
|
Leszek Koltunski
|
if( jumpToSolvedRecursive(quats,i,1,lastA,lastR,solution) )
|
414 |
aa0757b6
|
Leszek Koltunski
|
{
|
415 |
|
|
solution[0][0] = i;
|
416 |
bdcb662f
|
Leszek Koltunski
|
return solution;
|
417 |
aa0757b6
|
Leszek Koltunski
|
}
|
418 |
bdcb662f
|
Leszek Koltunski
|
|
419 |
00947987
|
Leszek Koltunski
|
return null;
|
420 |
|
|
}
|
421 |
bdcb662f
|
Leszek Koltunski
|
|
422 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
423 |
|
|
|
424 |
|
|
private int[][] concatenateMoves(int[][] high, int[][] jump1, int[][] mid, int[][] jump2)
|
425 |
|
|
{
|
426 |
|
|
int len1 = high ==null ? 0 : high.length-1;
|
427 |
cd595931
|
Leszek Koltunski
|
int len2 = jump1==null ? 0 : jump1[0][2];
|
428 |
bdcb662f
|
Leszek Koltunski
|
int len3 = mid ==null ? 0 : mid.length-1;
|
429 |
aa0757b6
|
Leszek Koltunski
|
int len4 = jump2==null ? 0 : jump2[0][0];
|
430 |
bdcb662f
|
Leszek Koltunski
|
|
431 |
|
|
int[][] moves = new int[len1+len2+len3+len4][];
|
432 |
|
|
int index = 0;
|
433 |
|
|
|
434 |
|
|
for(int i=0; i<len1; i++) moves[index++] = high[i+1];
|
435 |
|
|
for(int i=0; i<len2; i++) moves[index++] = jump1[i+1];
|
436 |
|
|
for(int i=0; i<len3; i++) moves[index++] = mid[i+1];
|
437 |
|
|
for(int i=0; i<len4; i++) moves[index++] = jump2[i+1];
|
438 |
|
|
|
439 |
|
|
convertMoves(moves);
|
440 |
|
|
|
441 |
|
|
return moves;
|
442 |
|
|
}
|
443 |
|
|
|
444 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
445 |
|
|
|
446 |
00e83f23
|
Leszek Koltunski
|
public int[][] solution(int index, int[] extra, OperatingSystemInterface osi)
|
447 |
bdcb662f
|
Leszek Koltunski
|
{
|
448 |
295f5302
|
Leszek Koltunski
|
if( isSolved(index) ) return null;
|
449 |
bdcb662f
|
Leszek Koltunski
|
int lastA=-1, lastR=0;
|
450 |
|
|
int[][] highMoves = traverseBlock(index,mHighTables,lastA,lastR);
|
451 |
|
|
|
452 |
|
|
if( highMoves!=null )
|
453 |
|
|
{
|
454 |
|
|
index = highMoves[0][0];
|
455 |
|
|
int len = highMoves.length;
|
456 |
|
|
lastA = highMoves[len-1][0];
|
457 |
|
|
lastR = highMoves[len-1][1];
|
458 |
|
|
}
|
459 |
|
|
|
460 |
|
|
int maxJump = Math.max(mLowestHigh-1-mHighestMid,mLowestMid/2);
|
461 |
5b9d6595
|
Leszek Koltunski
|
int[][] jump1Moves = jumpToMidOrSolved(index,maxJump,lastA,lastR);
|
462 |
bdcb662f
|
Leszek Koltunski
|
|
463 |
|
|
if( jump1Moves!=null )
|
464 |
|
|
{
|
465 |
5b9d6595
|
Leszek Koltunski
|
if( isSolved(jump1Moves[0][0]) )
|
466 |
bdcb662f
|
Leszek Koltunski
|
{
|
467 |
cd595931
|
Leszek Koltunski
|
return concatenateMoves(null,jump1Moves,null,null);
|
468 |
bdcb662f
|
Leszek Koltunski
|
}
|
469 |
|
|
if( jump1Moves[0][1]==mLowestMid )
|
470 |
|
|
{
|
471 |
5b9d6595
|
Leszek Koltunski
|
int[][] jump2Moves = jumpToSolved(index,mLowestMid-1,-1,0);
|
472 |
00e83f23
|
Leszek Koltunski
|
if( jump2Moves==null )
|
473 |
|
|
{
|
474 |
b2eb9a1d
|
Leszek Koltunski
|
osi.reportError("1 error jumping to Solved: "+index);
|
475 |
00e83f23
|
Leszek Koltunski
|
return null;
|
476 |
|
|
}
|
477 |
bdcb662f
|
Leszek Koltunski
|
return concatenateMoves(null,null,null,jump2Moves);
|
478 |
|
|
}
|
479 |
|
|
|
480 |
|
|
index = jump1Moves[0][0];
|
481 |
cd595931
|
Leszek Koltunski
|
int len = jump1Moves[0][2];
|
482 |
|
|
lastA = jump1Moves[len][0];
|
483 |
|
|
lastR = jump1Moves[len][1];
|
484 |
bdcb662f
|
Leszek Koltunski
|
}
|
485 |
|
|
|
486 |
|
|
int[][] midMoves = traverseBlock(index,mMidTables,lastA,lastR);
|
487 |
|
|
if( midMoves!=null )
|
488 |
|
|
{
|
489 |
|
|
index = midMoves[0][0];
|
490 |
|
|
int len = midMoves.length;
|
491 |
|
|
lastA = midMoves[len-1][0];
|
492 |
|
|
lastR = midMoves[len-1][1];
|
493 |
|
|
}
|
494 |
00e83f23
|
Leszek Koltunski
|
else
|
495 |
|
|
{
|
496 |
20d7d940
|
Leszek Koltunski
|
osi.reportError("error traversing mid Tables: "+index);
|
497 |
00e83f23
|
Leszek Koltunski
|
return null;
|
498 |
|
|
}
|
499 |
5b9d6595
|
Leszek Koltunski
|
int[][] jump2Moves = jumpToSolved(index,mLowestMid-1,lastA,lastR);
|
500 |
00e83f23
|
Leszek Koltunski
|
if( jump2Moves==null )
|
501 |
|
|
{
|
502 |
20d7d940
|
Leszek Koltunski
|
osi.reportError("2 error jumping to Solved: "+index);
|
503 |
00e83f23
|
Leszek Koltunski
|
return null;
|
504 |
|
|
}
|
505 |
bdcb662f
|
Leszek Koltunski
|
return concatenateMoves(highMoves,jump1Moves,midMoves,jump2Moves);
|
506 |
|
|
}
|
507 |
00947987
|
Leszek Koltunski
|
}
|