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.