| 52 |
52 |
|
| 53 |
53 |
private static final int[] FACE_COLORS = new int[]
|
| 54 |
54 |
{
|
| 55 |
|
COLOR_GREY , COLOR_VIOLET,
|
| 56 |
|
COLOR_YELLOW, COLOR_WHITE ,
|
| 57 |
|
COLOR_BLUE , COLOR_RED ,
|
| 58 |
|
COLOR_ORANGE, COLOR_GREEN
|
|
55 |
COLOR_ORANGE, COLOR_VIOLET,
|
|
56 |
COLOR_WHITE , COLOR_BLUE ,
|
|
57 |
COLOR_YELLOW, COLOR_RED ,
|
|
58 |
COLOR_GREEN , COLOR_GREY
|
| 59 |
59 |
};
|
| 60 |
60 |
|
| 61 |
61 |
// All legal rotation quats of a Diamond: unit + three 180 deg turns + 8 generators
|
| ... | ... | |
| 78 |
78 |
|
| 79 |
79 |
private static final float DIST = 0.50f;
|
| 80 |
80 |
|
| 81 |
|
// Colors of the faces of cubits. Each cubit has 8 faces
|
| 82 |
|
private static final int[][] mOctaFaceMap = new int[][]
|
|
81 |
private static final int[][] mFaceNeutralQuatIndex = new int[][]
|
| 83 |
82 |
{
|
| 84 |
|
{ 6,1,8,8, 2,5,8,8 },
|
| 85 |
|
{ 8,1,3,8, 8,5,7,8 },
|
| 86 |
|
{ 8,8,3,4, 8,8,7,0 },
|
| 87 |
|
{ 6,8,8,4, 2,8,8,0 },
|
| 88 |
|
{ 6,1,3,4, 8,8,8,8 },
|
| 89 |
|
{ 8,8,8,8, 2,5,7,0 },
|
|
83 |
{6,10},
|
|
84 |
{4, 8},
|
|
85 |
{7,11},
|
|
86 |
{5, 9},
|
|
87 |
{7,11},
|
|
88 |
{5, 9},
|
|
89 |
{6,10},
|
|
90 |
{4, 8}
|
| 90 |
91 |
};
|
| 91 |
92 |
|
| 92 |
|
private static final int[] mTetraFaceMap = new int[] { 1, 3, 4, 6, 5, 7, 0, 2 };
|
| 93 |
|
|
| 94 |
93 |
private static MeshBase mOctaMesh, mTetraMesh;
|
| 95 |
94 |
|
| 96 |
95 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| ... | ... | |
| 313 |
312 |
{
|
| 314 |
313 |
switch(tetra)
|
| 315 |
314 |
{
|
| 316 |
|
case 0 : return 0;
|
| 317 |
|
case 1 : return 1;
|
| 318 |
|
case 2 : return 2;
|
| 319 |
|
case 3 : return 3;
|
| 320 |
|
case 4 : return 4;
|
| 321 |
|
case 5 : return 5;
|
| 322 |
|
case 6 : return 6;
|
| 323 |
|
case 7 : return 7;
|
|
315 |
case 0 : return 1;
|
|
316 |
case 1 : return 2;
|
|
317 |
case 2 : return 3;
|
|
318 |
case 3 : return 0;
|
|
319 |
case 4 : return 5;
|
|
320 |
case 5 : return 6;
|
|
321 |
case 6 : return 7;
|
|
322 |
case 7 : return 4;
|
| 324 |
323 |
default: return 8;
|
| 325 |
324 |
}
|
| 326 |
325 |
}
|
| ... | ... | |
| 333 |
332 |
|
| 334 |
333 |
switch( retFaceTetraBelongsTo(cubit-numO, numLayers) )
|
| 335 |
334 |
{
|
| 336 |
|
case 0: return new Static4D(0,-SQ2/2,0,SQ2/2); // 90 along Y
|
| 337 |
|
case 1: return QUATS[1]; // 180 along Y
|
| 338 |
|
case 2: return new Static4D(0,+SQ2/2,0,SQ2/2); // 90 along Y
|
| 339 |
|
case 3: return QUATS[0]; // unit quat
|
| 340 |
|
case 4: return new Static4D(SQ2/2, 0,SQ2/2,0); //
|
| 341 |
|
case 5: return new Static4D( 1,0,0, 0); // 180 along X
|
| 342 |
|
case 6: return new Static4D(-SQ2/2,0,SQ2/2,0); //
|
| 343 |
|
case 7: return new Static4D(0, 0,1, 0); // 180 along Z
|
|
335 |
case 0: return QUATS[0]; // unit quat
|
|
336 |
case 1: return new Static4D(0,-SQ2/2,0,SQ2/2); // 90 along Y
|
|
337 |
case 2: return QUATS[1]; // 180 along Y
|
|
338 |
case 3: return new Static4D(0,+SQ2/2,0,SQ2/2); // 90 along
|
|
339 |
case 4: return new Static4D(0, 0,1, 0); // 180 along Z
|
|
340 |
case 5: return new Static4D(SQ2/2, 0,SQ2/2,0); //
|
|
341 |
case 6: return new Static4D( 1,0,0, 0); // 180 along X
|
|
342 |
case 7: return new Static4D(-SQ2/2,0,SQ2/2,0); //
|
| 344 |
343 |
}
|
| 345 |
344 |
|
| 346 |
345 |
return null;
|
| ... | ... | |
| 372 |
371 |
}
|
| 373 |
372 |
|
| 374 |
373 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 375 |
|
// TODO
|
| 376 |
374 |
|
| 377 |
|
int getFaceColor(int cubit, int cubitface, int numLayers)
|
|
375 |
int getFaceColor(int cubit, int cubitface, int size)
|
| 378 |
376 |
{
|
| 379 |
|
int numO = getNumOctahedrons(numLayers);
|
|
377 |
int numO = getNumOctahedrons(size);
|
| 380 |
378 |
|
| 381 |
379 |
if( cubit<numO )
|
| 382 |
380 |
{
|
| 383 |
|
return mOctaFaceMap[cubit][cubitface];
|
|
381 |
int axis = 0;
|
|
382 |
int layer= 1;
|
|
383 |
|
|
384 |
switch(cubitface)
|
|
385 |
{
|
|
386 |
case 0: axis = 2; layer = 1; break;
|
|
387 |
case 1: axis = 0; layer = (1<<(size-1)); break;
|
|
388 |
case 2: axis = 3; layer = 1; break;
|
|
389 |
case 3: axis = 1; layer = (1<<(size-1)); break;
|
|
390 |
case 4: axis = 3; layer = (1<<(size-1)); break;
|
|
391 |
case 5: axis = 1; layer = 1; break;
|
|
392 |
case 6: axis = 2; layer = (1<<(size-1)); break;
|
|
393 |
case 7: axis = 0; layer = 1; break;
|
|
394 |
}
|
|
395 |
|
|
396 |
return CUBITS[cubit].mRotationRow[axis] == layer ? cubitface : NUM_FACES;
|
| 384 |
397 |
}
|
| 385 |
398 |
else
|
| 386 |
399 |
{
|
| 387 |
|
return cubitface>0 ? 8 : mTetraFaceMap[retFaceTetraBelongsTo(cubit-numO, numLayers)];
|
|
400 |
return cubitface>0 ? NUM_FACES : retFaceTetraBelongsTo(cubit-numO, size);
|
| 388 |
401 |
}
|
| 389 |
402 |
}
|
| 390 |
403 |
|
| ... | ... | |
| 508 |
521 |
}
|
| 509 |
522 |
|
| 510 |
523 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 511 |
|
// The Diamond is solved if and only if:
|
|
524 |
// The (2 and 3-layered) Diamond is solved if and only if:
|
| 512 |
525 |
//
|
| 513 |
|
// 1) all 6 octahedrons are rotated with the same quat
|
| 514 |
|
// 2) the 8 tetrahedrons are rotated with the quat and, optionally, the can also be rotated
|
| 515 |
|
// by multitudes of 120 degrees along the face they are the center of.
|
|
526 |
// 1) all octahedrons are rotated with the same quat
|
|
527 |
// 2) all tetrahedrons might be also optionally rotated by a 'face neutral' pair of quats
|
|
528 |
// (indexes of those are kept in the 'mFaceNeutralQuattIndex' table)
|
| 516 |
529 |
//
|
| 517 |
|
// so:
|
| 518 |
|
// 1) cubits 6,12: can also be QUAT 6,10
|
| 519 |
|
// 2) cubits 7,13: can also be QUAT 4,8
|
| 520 |
|
// 3) cubits 8,10: can also be QUAT 7,11
|
| 521 |
|
// 4) cubits 9,11: can also be QUAT 5,9
|
| 522 |
|
// TODO
|
|
530 |
// Note: this doesn't work for numLayers > 3, because then we have some 'internal' octahedrons,
|
|
531 |
// which also might be rotate by 'face neutral' pair of quats. We don't care about this (yet?)
|
| 523 |
532 |
|
| 524 |
533 |
public boolean isSolved()
|
| 525 |
534 |
{
|
| 526 |
535 |
int q = CUBITS[0].mQuatIndex;
|
|
536 |
int layers = getNumLayers();
|
|
537 |
int numO = getNumOctahedrons(layers);
|
| 527 |
538 |
|
| 528 |
|
if ( CUBITS[ 1].mQuatIndex == q &&
|
| 529 |
|
CUBITS[ 2].mQuatIndex == q &&
|
| 530 |
|
CUBITS[ 3].mQuatIndex == q &&
|
| 531 |
|
CUBITS[ 4].mQuatIndex == q &&
|
| 532 |
|
CUBITS[ 5].mQuatIndex == q )
|
|
539 |
for(int i=1; i<numO; i++)
|
| 533 |
540 |
{
|
| 534 |
|
int q1 = mulQuat(q,5);
|
| 535 |
|
int q2 = mulQuat(q,9);
|
| 536 |
|
|
| 537 |
|
if( CUBITS[ 9].mQuatIndex != q && CUBITS[ 9].mQuatIndex != q1 && CUBITS[ 9].mQuatIndex != q2 ) return false;
|
| 538 |
|
if( CUBITS[11].mQuatIndex != q && CUBITS[11].mQuatIndex != q1 && CUBITS[11].mQuatIndex != q2 ) return false;
|
| 539 |
|
|
| 540 |
|
q1 = mulQuat(q,4);
|
| 541 |
|
q2 = mulQuat(q,8);
|
| 542 |
|
|
| 543 |
|
if( CUBITS[ 7].mQuatIndex != q && CUBITS[ 7].mQuatIndex != q1 && CUBITS[ 7].mQuatIndex != q2 ) return false;
|
| 544 |
|
if( CUBITS[13].mQuatIndex != q && CUBITS[13].mQuatIndex != q1 && CUBITS[13].mQuatIndex != q2 ) return false;
|
| 545 |
|
|
| 546 |
|
q1 = mulQuat(q,6);
|
| 547 |
|
q2 = mulQuat(q,10);
|
| 548 |
|
|
| 549 |
|
if( CUBITS[ 6].mQuatIndex != q && CUBITS[ 6].mQuatIndex != q1 && CUBITS[ 6].mQuatIndex != q2 ) return false;
|
| 550 |
|
if( CUBITS[12].mQuatIndex != q && CUBITS[12].mQuatIndex != q1 && CUBITS[12].mQuatIndex != q2 ) return false;
|
|
541 |
if( CUBITS[i].mQuatIndex != q ) return false;
|
|
542 |
}
|
| 551 |
543 |
|
| 552 |
|
q1 = mulQuat(q,7);
|
| 553 |
|
q2 = mulQuat(q,11);
|
|
544 |
int qI, q1Index, q2Index, face;
|
| 554 |
545 |
|
| 555 |
|
if( CUBITS[ 8].mQuatIndex != q && CUBITS[ 8].mQuatIndex != q1 && CUBITS[ 8].mQuatIndex != q2 ) return false;
|
| 556 |
|
if( CUBITS[10].mQuatIndex != q && CUBITS[10].mQuatIndex != q1 && CUBITS[10].mQuatIndex != q2 ) return false;
|
|
546 |
for(int i=numO; i<NUM_CUBITS; i++)
|
|
547 |
{
|
|
548 |
face = retFaceTetraBelongsTo(i-numO,layers);
|
|
549 |
q1Index = mFaceNeutralQuatIndex[face][0];
|
|
550 |
q2Index = mFaceNeutralQuatIndex[face][1];
|
|
551 |
qI = CUBITS[i].mQuatIndex;
|
| 557 |
552 |
|
| 558 |
|
return true;
|
|
553 |
if( qI != q && qI != mulQuat(q,q1Index) && qI != mulQuat(q,q2Index) ) return false;
|
| 559 |
554 |
}
|
| 560 |
555 |
|
| 561 |
|
return false;
|
|
556 |
return true;
|
| 562 |
557 |
}
|
| 563 |
558 |
|
| 564 |
559 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| ... | ... | |
| 573 |
568 |
|
| 574 |
569 |
public int getObjectName(int numLayers)
|
| 575 |
570 |
{
|
| 576 |
|
return R.string.diam2;
|
|
571 |
switch(numLayers)
|
|
572 |
{
|
|
573 |
case 2: return R.string.diam2;
|
|
574 |
case 3: return R.string.diam3;
|
|
575 |
}
|
|
576 |
|
|
577 |
return 0;
|
| 577 |
578 |
}
|
| 578 |
579 |
|
| 579 |
580 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 580 |
581 |
|
| 581 |
582 |
public int getInventor(int numLayers)
|
| 582 |
583 |
{
|
| 583 |
|
return R.string.diam2_inventor;
|
|
584 |
switch(numLayers)
|
|
585 |
{
|
|
586 |
case 2: return R.string.diam2_inventor;
|
|
587 |
case 3: return R.string.diam3_inventor;
|
|
588 |
}
|
|
589 |
|
|
590 |
return 0;
|
| 584 |
591 |
}
|
| 585 |
592 |
|
| 586 |
593 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 587 |
594 |
|
| 588 |
595 |
public int getComplexity(int numLayers)
|
| 589 |
596 |
{
|
| 590 |
|
return 5;
|
|
597 |
switch(numLayers)
|
|
598 |
{
|
|
599 |
case 2: return 5;
|
|
600 |
case 3: return 7;
|
|
601 |
}
|
|
602 |
|
|
603 |
return 0;
|
| 591 |
604 |
}
|
| 592 |
605 |
}
|
Progress making the Diamond class support any size.