Project

General

Profile

Download (19.7 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / solvers / SolverPyraminx.java @ b8dab9fd

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.main.ObjectType;
16
import org.distorted.objectlib.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
18
import org.distorted.objectlib.tablebases.TablebaseHelpers;
19
import org.distorted.objectlib.tablebases.TablebasesAbstract;
20
import org.distorted.objectlib.tablebases.TablebasesPyraminx;
21

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

    
24
public class SolverPyraminx extends SolverTablebase
25
{
26
  private static final int ERROR_CORNER_GYB_MISSING = -1;
27
  private static final int ERROR_CORNER_GYR_MISSING = -2;
28
  private static final int ERROR_CORNER_GBR_MISSING = -3;
29
  private static final int ERROR_CORNER_YBR_MISSING = -4;
30

    
31
  private static final int ERROR_VERTEX_GYB_MISSING = -5;
32
  private static final int ERROR_VERTEX_GYR_MISSING = -6;
33
  private static final int ERROR_VERTEX_GBR_MISSING = -7;
34
  private static final int ERROR_VERTEX_YBR_MISSING = -8;
35

    
36
  private static final int ERROR_EDGE_RB_MISSING = -9;
37
  private static final int ERROR_EDGE_RY_MISSING = -10;
38
  private static final int ERROR_EDGE_RG_MISSING = -11;
39
  private static final int ERROR_EDGE_YB_MISSING = -12;
40
  private static final int ERROR_EDGE_GB_MISSING = -13;
41
  private static final int ERROR_EDGE_GY_MISSING = -14;
42

    
43
  private static final int ERROR_CORNERS_CANNOT   = -15;
44
  private static final int ERROR_VERTICES_CANNOT  = -16;
45
  private static final int ERROR_CORNER_TWISTED   = -17;
46
  private static final int ERROR_EDGE_TWISTED     = -18;
47
  private static final int ERROR_C_V_DONT_MATCH   = -19;
48
  private static final int ERROR_TWO_EDGES        = -20;
49

    
50
  private static final int[][] edgeColors = new int[][]
51
      {
52
          {3,2},{1,3},{0,3},{2,1},{2,0},{1,0}  // order of those pairs determines edge twist
53
      };
54

    
55
  private TablebasesAbstract mSolver;
56
  private int[] mCornerTwist;
57

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

    
60
  private boolean pieceEqual3(int[] piece, int c1, int c2, int c3)
61
    {
62
    return ( (piece[0]==c1 && piece[1]==c2 && piece[2]==c3) ||
63
             (piece[0]==c1 && piece[2]==c2 && piece[1]==c3) ||
64
             (piece[1]==c1 && piece[0]==c2 && piece[2]==c3) ||
65
             (piece[1]==c1 && piece[2]==c2 && piece[0]==c3) ||
66
             (piece[2]==c1 && piece[1]==c2 && piece[0]==c3) ||
67
             (piece[2]==c1 && piece[0]==c2 && piece[1]==c3)  );
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
  private boolean pieceEqual2(int[] piece, int[] colors)
73
    {
74
    return ( (piece[0]==colors[0] && piece[1]==colors[1]) ||
75
             (piece[0]==colors[1] && piece[1]==colors[0])  );
76
    }
77

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

    
80
  private int checkAllCornersPresent(int[][] corners)
81
    {
82
    boolean ybr = false;
83
    boolean gbr = false;
84
    boolean gyr = false;
85
    boolean gyb = false;
86

    
87
    for(int i=0; i<4; i++)
88
      {
89
      if( pieceEqual3(corners[i],0,1,2) ) gyb = true;
90
      if( pieceEqual3(corners[i],0,1,3) ) gyr = true;
91
      if( pieceEqual3(corners[i],0,2,3) ) gbr = true;
92
      if( pieceEqual3(corners[i],1,2,3) ) ybr = true;
93
      }
94

    
95
    if( !ybr ) return ERROR_CORNER_YBR_MISSING;
96
    if( !gbr ) return ERROR_CORNER_GBR_MISSING;
97
    if( !gyr ) return ERROR_CORNER_GYR_MISSING;
98
    if( !gyb ) return ERROR_CORNER_GYB_MISSING;
99

    
100
    return 0;
101
    }
102

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

    
105
  private int checkAllVerticesPresent(int[][] vertex)
106
    {
107
    boolean ybr = false;
108
    boolean gbr = false;
109
    boolean gyr = false;
110
    boolean gyb = false;
111

    
112
    for(int i=0; i<4; i++)
113
      {
114
      if( pieceEqual3(vertex[i],0,1,2) ) gyb = true;
115
      if( pieceEqual3(vertex[i],0,1,3) ) gyr = true;
116
      if( pieceEqual3(vertex[i],0,2,3) ) gbr = true;
117
      if( pieceEqual3(vertex[i],1,2,3) ) ybr = true;
118
      }
119

    
120
    if( !ybr ) return ERROR_VERTEX_YBR_MISSING;
121
    if( !gbr ) return ERROR_VERTEX_GBR_MISSING;
122
    if( !gyr ) return ERROR_VERTEX_GYR_MISSING;
123
    if( !gyb ) return ERROR_VERTEX_GYB_MISSING;
124

    
125
    return 0;
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
  private int checkAllEdgesPresent(int[][] edges)
131
    {
132
    boolean[] present = new boolean[6];
133
    for(int i=0; i<6; i++) present[i] = false;
134

    
135
    for(int i=0; i<6; i++)
136
      for(int j=0; j<6; j++)
137
        if (pieceEqual2(edges[i], edgeColors[j]))
138
          {
139
          present[j] = true;
140
          break;
141
          }
142

    
143
    if( !present[0] ) return ERROR_EDGE_RB_MISSING;
144
    if( !present[1] ) return ERROR_EDGE_RY_MISSING;
145
    if( !present[2] ) return ERROR_EDGE_RG_MISSING;
146
    if( !present[3] ) return ERROR_EDGE_YB_MISSING;
147
    if( !present[4] ) return ERROR_EDGE_GB_MISSING;
148
    if( !present[5] ) return ERROR_EDGE_GY_MISSING;
149

    
150
    return 0;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private int[] computeFaceColors(int[][] corners)
156
    {
157
    int[] ret = new int[4];
158

    
159
    for(int i=0; i<4; i++)
160
      for(int j=0; j<4; j++)
161
        if( corners[i][0]!=j && corners[i][1]!=j && corners[i][2]!=j ) ret[i]=j;
162

    
163
    return ret;
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  private int checkAgreement(int[] faces1, int[] faces2)
169
    {
170
    for(int i=0; i<4; i++)
171
      if( faces1[i]!=faces2[i] ) return ERROR_C_V_DONT_MATCH;
172

    
173
    return 0;
174
    }
175

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

    
178
  private int computePieceTwist(int index, int[] corner, int[] faceColor)
179
    {
180
    int twist1=0, twist2=0, twist3=0;
181

    
182
    switch(index)
183
      {
184
      case 0: if( corner[1]==faceColor[1] ) twist1=1;
185
              if( corner[2]==faceColor[1] ) twist1=2;
186
              if( corner[0]==faceColor[2] ) twist2=2;
187
              if( corner[2]==faceColor[2] ) twist2=1;
188
              if( corner[0]==faceColor[3] ) twist3=1;
189
              if( corner[1]==faceColor[3] ) twist3=2;
190
              break;
191
      case 1: if( corner[1]==faceColor[0] ) twist1=1;
192
              if( corner[2]==faceColor[0] ) twist1=2;
193
              if( corner[0]==faceColor[2] ) twist2=1;
194
              if( corner[1]==faceColor[2] ) twist2=2;
195
              if( corner[0]==faceColor[3] ) twist3=2;
196
              if( corner[2]==faceColor[3] ) twist3=1;
197
              break;
198
      case 2: if( corner[1]==faceColor[0] ) twist1=1;
199
              if( corner[2]==faceColor[0] ) twist1=2;
200
              if( corner[0]==faceColor[1] ) twist2=2;
201
              if( corner[2]==faceColor[1] ) twist2=1;
202
              if( corner[0]==faceColor[3] ) twist3=1;
203
              if( corner[1]==faceColor[3] ) twist3=2;
204
              break;
205
      case 3: if( corner[1]==faceColor[0] ) twist1=1;
206
              if( corner[2]==faceColor[0] ) twist1=2;
207
              if( corner[0]==faceColor[1] ) twist2=1;
208
              if( corner[1]==faceColor[1] ) twist2=2;
209
              if( corner[0]==faceColor[2] ) twist3=2;
210
              if( corner[2]==faceColor[2] ) twist3=1;
211
              break;
212
      }
213

    
214
    return ( twist1!=twist2 || twist1!=twist3 ) ? ERROR_CORNERS_CANNOT : twist1;
215
    }
216

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

    
219
  private int locateEdge(int[][] edges, int[] colors)
220
    {
221
    for(int i=0; i<6; i++)
222
      if( edges[i][0]==colors[0] && edges[i][1]==colors[1] ||
223
          edges[i][0]==colors[1] && edges[i][1]==colors[0]  ) return i;
224

    
225
    return -1;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private int edgeTwist(int[] edge, int[] colors)
231
    {
232
    return edge[0]==colors[0] ? 0:1;
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  private int[] computeEdgeQuats(int[][] edges)
238
    {
239
    int[] quats = new int[6];
240

    
241
    for(int i=0; i<6; i++)
242
      {
243
      int pos   = locateEdge(edges,edgeColors[i]);
244
      int twist = edgeTwist(edges[pos],edgeColors[i]);
245
      quats[i]  = TablebasesPyraminx.EDGE_QUATS[pos][twist];
246
      }
247

    
248
    return quats;
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  public SolverPyraminx(Resources res, TwistyObject object)
254
    {
255
    super(res,object);
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

    
260
  private void getCorners(TwistyObject object, int[][] corners)
261
    {
262
    corners[0][0] = object.getCubitFaceStickerIndex(4,0);  // G
263
    corners[0][1] = object.getCubitFaceStickerIndex(4,3);  // R
264
    corners[0][2] = object.getCubitFaceStickerIndex(4,2);  // B
265

    
266
    corners[1][0] = object.getCubitFaceStickerIndex(6,1);  // Y
267
    corners[1][1] = object.getCubitFaceStickerIndex(6,2);  // B
268
    corners[1][2] = object.getCubitFaceStickerIndex(6,3);  // R
269

    
270
    corners[2][0] = object.getCubitFaceStickerIndex(11,1);  // Y
271
    corners[2][1] = object.getCubitFaceStickerIndex(11,0);  // G
272
    corners[2][2] = object.getCubitFaceStickerIndex(11,2);  // B
273

    
274
    corners[3][0] = object.getCubitFaceStickerIndex(13,1);  // Y
275
    corners[3][1] = object.getCubitFaceStickerIndex(13,3);  // R
276
    corners[3][2] = object.getCubitFaceStickerIndex(13,0);  // G
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  private void getVertices(TwistyObject object, int[][] vertex)
282
    {
283
    vertex[0][0] = object.getCubitFaceStickerIndex(0,0);  // G
284
    vertex[0][1] = object.getCubitFaceStickerIndex(0,5);  // R
285
    vertex[0][2] = object.getCubitFaceStickerIndex(0,7);  // B
286

    
287
    vertex[1][0] = object.getCubitFaceStickerIndex(1,2);  // Y
288
    vertex[1][1] = object.getCubitFaceStickerIndex(1,7);  // B
289
    vertex[1][2] = object.getCubitFaceStickerIndex(1,5);  // R
290

    
291
    vertex[2][0] = object.getCubitFaceStickerIndex(2,2);  // Y
292
    vertex[2][1] = object.getCubitFaceStickerIndex(2,0);  // G
293
    vertex[2][2] = object.getCubitFaceStickerIndex(2,7);  // B
294

    
295
    vertex[3][0] = object.getCubitFaceStickerIndex(3,2);  // Y
296
    vertex[3][1] = object.getCubitFaceStickerIndex(3,5);  // R
297
    vertex[3][2] = object.getCubitFaceStickerIndex(3,0);  // G
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  private void getEdges(TwistyObject object, int[][] edges)
303
    {
304
    edges[0][0] = object.getCubitFaceStickerIndex(5,3);  // R
305
    edges[0][1] = object.getCubitFaceStickerIndex(5,2);  // B
306

    
307
    edges[1][0] = object.getCubitFaceStickerIndex(10,1); // Y
308
    edges[1][1] = object.getCubitFaceStickerIndex(10,3); // R
309

    
310
    edges[2][0] = object.getCubitFaceStickerIndex(9,0);  // G
311
    edges[2][1] = object.getCubitFaceStickerIndex(9,3);  // R
312

    
313
    edges[3][0] = object.getCubitFaceStickerIndex(8,2);  // B
314
    edges[3][1] = object.getCubitFaceStickerIndex(8,1);  // Y
315

    
316
    edges[4][0] = object.getCubitFaceStickerIndex(7,2);  // B
317
    edges[4][1] = object.getCubitFaceStickerIndex(7,0);  // G
318

    
319
    edges[5][0] = object.getCubitFaceStickerIndex(12,1); // Y
320
    edges[5][1] = object.getCubitFaceStickerIndex(12,0); // G
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
  public int tablebaseIndex(TwistyObject object)
326
    {
327
    int[][] corners = new int[4][3];
328
    int[][] edges   = new int[6][2];
329
    int[][] vertices= new int[4][3];
330
    int[] vertex_twist = new int[4];
331
    mCornerTwist = new int[4];
332

    
333
    getCorners(object,corners);
334
    getVertices(object,vertices);
335
    getEdges(object,edges);
336

    
337
    int result1 = checkAllCornersPresent(corners);
338
    if( result1<0 ) return result1;
339

    
340
    int result2 = checkAllVerticesPresent(vertices);
341
    if( result2<0 ) return result2;
342

    
343
    int result3 = checkAllEdgesPresent(edges);
344
    if( result3<0 ) return result3;
345

    
346
    int[] faces1 = computeFaceColors(corners);
347
    int[] faces2 = computeFaceColors(vertices);
348

    
349
    int result4 = checkAgreement(faces1,faces2);
350
    if( result4<0 ) return result4;
351

    
352
    for(int i=0; i<4; i++)
353
      {
354
      mCornerTwist[i] = computePieceTwist(i,corners[i],faces1);
355
      if( mCornerTwist[i]<0 ) return ERROR_CORNERS_CANNOT;
356
      }
357

    
358
    for(int i=0; i<4; i++)
359
      {
360
      vertex_twist[i] = computePieceTwist(i,vertices[i],faces1);
361
      if( vertex_twist[i]<0 ) return ERROR_VERTICES_CANNOT;
362
      }
363

    
364
    int[] quats = computeEdgeQuats(edges);
365
    int[] permutation = new int[6];
366
    TablebasesPyraminx.getEdgePermutation(permutation,quats,0);
367
    boolean even = TablebaseHelpers.permutationIsEven(permutation);
368
    if( !even ) return ERROR_TWO_EDGES;
369
    int[] edge_twist = new int[6];
370
    TablebasesPyraminx.getEdgeTwist(edge_twist,quats,0);
371

    
372
    int totalEdgeTwist=0;
373
    for(int i=0; i<6; i++) totalEdgeTwist += edge_twist[i];
374
    if( (totalEdgeTwist%2)!=0 ) return ERROR_EDGE_TWISTED;
375

    
376
    int vertexTwist = vertex_twist[0]+ 3*(vertex_twist[1]+ 3*(vertex_twist[2]+ 3*vertex_twist[3]));
377
    int edgeTwist = edge_twist[0]+ 2*(edge_twist[1]+ 2*(edge_twist[2]+ 2*(edge_twist[3]+ 2*edge_twist[4])));
378
    int perm_num = TablebaseHelpers.computeEvenPermutationNum(permutation);
379

    
380
    return vertexTwist + 81*(edgeTwist + 32*perm_num);
381
    }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

    
385
  private int getColorIndex3(int color)
386
    {
387
    switch(color)
388
      {
389
      case 0: return R.string.color_green3;
390
      case 1: return R.string.color_yellow3;
391
      case 2: return R.string.color_blue3;
392
      case 3: return R.string.color_red3;
393
      }
394

    
395
    return -1;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  private int getColorIndex4(int color)
401
    {
402
    switch(color)
403
      {
404
      case 0: return R.string.color_green4;
405
      case 1: return R.string.color_yellow4;
406
      case 2: return R.string.color_blue4;
407
      case 3: return R.string.color_red4;
408
      }
409

    
410
    return -1;
411
    }
412

    
413
///////////////////////////////////////////////////////////////////////////////////////////////////
414

    
415
  private int getColorIndex6(int color)
416
    {
417
    switch(color)
418
      {
419
      case 0: return R.string.color_green6;
420
      case 1: return R.string.color_yellow6;
421
      case 2: return R.string.color_blue6;
422
      case 3: return R.string.color_red6;
423
      }
424

    
425
    return -1;
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  private String cornerError(Resources res, int color0, int color1, int color2)
431
    {
432
    int j0 = getColorIndex3(color0);
433
    int j1 = getColorIndex3(color1);
434
    int j2 = getColorIndex4(color2);
435

    
436
    String c0 = res.getString(j0);
437
    String c1 = res.getString(j1);
438
    String c2 = res.getString(j2);
439

    
440
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
441
    }
442

    
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444

    
445
  private String vertexError(Resources res, int color0, int color1, int color2)
446
    {
447
    int j0 = getColorIndex3(color0);
448
    int j1 = getColorIndex3(color1);
449
    int j2 = getColorIndex4(color2);
450

    
451
    String c0 = res.getString(j0);
452
    String c1 = res.getString(j1);
453
    String c2 = res.getString(j2);
454

    
455
    return res.getString(R.string.solver_generic_missing_vertex,c0,c1,c2);
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  private String edgeError(Resources res, int color0, int color1)
461
    {
462
    int j0 = getColorIndex3(color0);
463
    int j1 = getColorIndex6(color1);
464

    
465
    String c0 = res.getString(j0);
466
    String c1 = res.getString(j1);
467

    
468
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

    
473
  public String error(int index, Resources res)
474
    {
475
    switch(index)
476
      {
477
      case ERROR_CORNER_YBR_MISSING: return cornerError(res,3,2,1);
478
      case ERROR_CORNER_GBR_MISSING: return cornerError(res,3,2,0);
479
      case ERROR_CORNER_GYR_MISSING: return cornerError(res,3,1,0);
480
      case ERROR_CORNER_GYB_MISSING: return cornerError(res,2,1,0);
481
      case ERROR_VERTEX_YBR_MISSING: return vertexError(res,3,2,1);
482
      case ERROR_VERTEX_GBR_MISSING: return vertexError(res,3,2,0);
483
      case ERROR_VERTEX_GYR_MISSING: return vertexError(res,3,1,0);
484
      case ERROR_VERTEX_GYB_MISSING: return vertexError(res,2,1,0);
485
      case ERROR_EDGE_RB_MISSING   : return edgeError(res,3,2);
486
      case ERROR_EDGE_RY_MISSING   : return edgeError(res,3,1);
487
      case ERROR_EDGE_RG_MISSING   : return edgeError(res,3,0);
488
      case ERROR_EDGE_YB_MISSING   : return edgeError(res,2,1);
489
      case ERROR_EDGE_GB_MISSING   : return edgeError(res,2,0);
490
      case ERROR_EDGE_GY_MISSING   : return edgeError(res,1,0);
491
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
492
      case ERROR_EDGE_TWISTED      : return res.getString(R.string.solver_generic_edge_twist);
493
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
494
      case ERROR_VERTICES_CANNOT   : return res.getString(R.string.solver_generic_vertices_cannot);
495
      case ERROR_C_V_DONT_MATCH    : return res.getString(R.string.solver_generic_c_v_dont_match);
496
      case ERROR_TWO_EDGES         : return res.getString(R.string.solver_generic_two_edges);
497
      }
498

    
499
    return null;
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  private void addMove(int[] move, int axis, int twist)
505
    {
506
    move[0] = axis;
507
    move[1] = (1<<2);
508
    move[2] = (twist==2 ? -1:twist);
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
  private int[][] constructTipMoves(int[] twist)
514
    {
515
    int total = 0;
516

    
517
    for(int i=0; i<4; i++)
518
      if( twist[i]!=0 ) total++;
519

    
520
    if( total>0 )
521
      {
522
      int[][] moves = new int[total][3];
523

    
524
      int index=0;
525
      if( twist[0]!=0 ) { addMove(moves[index],1,twist[0]); index++; }
526
      if( twist[1]!=0 ) { addMove(moves[index],0,twist[1]); index++; }
527
      if( twist[2]!=0 ) { addMove(moves[index],3,twist[2]); index++; }
528
      if( twist[3]!=0 ) { addMove(moves[index],2,twist[3]);          }
529

    
530
      return moves;
531
      }
532

    
533
    return null;
534
    }
535

    
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537

    
538
  public int[][] solution(int index, Resources res)
539
    {
540
    if( mSolver==null )
541
      {
542
      mSolver = ImplementedTablebasesList.createPacked(res,ObjectType.PYRA_3);
543
      }
544

    
545
    int[][] moves1 = mSolver!=null ? mSolver.solution(index) : null;
546
    int[][] moves2 = constructTipMoves(mCornerTwist);
547

    
548
    int len1 = (moves1==null ? 0:moves1.length);
549
    int len2 = (moves2==null ? 0:moves2.length);
550

    
551
    int[][] moves = new int[len1+len2][];
552

    
553
android.util.Log.e("D", "len1="+len1+" len2="+len2);
554

    
555
    if( len1>0 ) System.arraycopy(moves1, 0, moves,    0, len1);
556
    if( len2>0 ) System.arraycopy(moves2, 0, moves, len1, len2);
557

    
558
    return moves;
559
    }
560
}  
561

    
(6-6/8)