Revision 2ef489e2
Added by Leszek Koltunski about 3 years ago
src/main/java/org/distorted/objects/TwistyDiamond.java | ||
---|---|---|
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 |
} |
Also available in: Unified diff
Progress making the Diamond class support any size.