40 |
40 |
|
41 |
41 |
class TwistySquare1 extends TwistyObject
|
42 |
42 |
{
|
|
43 |
private static final int LAST_SL = 0; // automatic rotations: last rot was a 'slash' i.e. along ROT_AXIS[1]
|
|
44 |
private static final int LAST_UP = 1; // last rot was along ROT_AXIS[0], upper layer and forelast was a slash
|
|
45 |
private static final int LAST_LO = 2; // last rot was along ROT_AXIS[0], lower layer and forelast was a slash
|
|
46 |
private static final int LAST_UL = 3; // two last rots were along ROT_AXIS[0] (so the next must be a slash)
|
|
47 |
|
43 |
48 |
private static final float COS15 = (SQ6+SQ2)/4;
|
44 |
49 |
private static final float SIN15 = (SQ6-SQ2)/4;
|
45 |
50 |
private static final float X = 3*(2-SQ3)/2;
|
... | ... | |
232 |
237 |
{
|
233 |
238 |
{ 2, 8,17,23},
|
234 |
239 |
{ 5,11,14,20},
|
235 |
|
{ 8, 2,23,17},
|
236 |
|
{11, 5,20,14},
|
237 |
|
{17,23, 2, 8},
|
238 |
|
{14,20, 5,11},
|
239 |
|
{23,17, 8, 2},
|
240 |
|
{20,14,11, 5}
|
241 |
240 |
};
|
242 |
241 |
|
243 |
|
// QUAT[i]*QUAT[j] = QUAT_MULT[i][j]
|
|
242 |
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
|
244 |
243 |
private static final int[][] QUAT_MULT = new int[][]
|
245 |
244 |
{
|
246 |
245 |
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
|
... | ... | |
271 |
270 |
|
272 |
271 |
private static MeshBase[] mMeshes;
|
273 |
272 |
|
|
273 |
private final int[][] mPermittedAngles;
|
|
274 |
private final int[] mCornerQuat;
|
|
275 |
private int mLastRot, mPermittedUp, mPermittedDo;
|
|
276 |
|
274 |
277 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
275 |
278 |
|
276 |
279 |
TwistySquare1(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
|
277 |
280 |
DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
|
278 |
281 |
{
|
279 |
282 |
super(size, size, quat, texture, mesh, effects, moves, ObjectList.SQU1, res, scrWidth);
|
|
283 |
|
|
284 |
mLastRot = LAST_SL;
|
|
285 |
mPermittedAngles = new int[2][BASIC_ANGLE[0]];
|
|
286 |
mCornerQuat = new int[8];
|
280 |
287 |
}
|
281 |
288 |
|
282 |
289 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
503 |
510 |
return rowBitmap;
|
504 |
511 |
}
|
505 |
512 |
|
|
513 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
514 |
|
|
515 |
private boolean cornerIsUp(int index)
|
|
516 |
{
|
|
517 |
return ((index<4) ^ (mCornerQuat[index]>=12));
|
|
518 |
}
|
|
519 |
|
|
520 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
521 |
|
|
522 |
private boolean cornerIsLeft(int index)
|
|
523 |
{
|
|
524 |
int q = mCornerQuat[index];
|
|
525 |
|
|
526 |
switch(index)
|
|
527 |
{
|
|
528 |
case 0:
|
|
529 |
case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
|
|
530 |
case 1:
|
|
531 |
case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
|
|
532 |
case 2:
|
|
533 |
case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
|
|
534 |
case 3:
|
|
535 |
case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
|
|
536 |
}
|
|
537 |
|
|
538 |
return false;
|
|
539 |
}
|
|
540 |
|
|
541 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
542 |
|
|
543 |
private boolean quatIsBad(int quatIndex, int corner)
|
|
544 |
{
|
|
545 |
int index = (corner%2);
|
|
546 |
|
|
547 |
return ( quatIndex==BAD_CORNER_QUATS[index][0] ||
|
|
548 |
quatIndex==BAD_CORNER_QUATS[index][1] ||
|
|
549 |
quatIndex==BAD_CORNER_QUATS[index][2] ||
|
|
550 |
quatIndex==BAD_CORNER_QUATS[index][3] );
|
|
551 |
}
|
|
552 |
|
|
553 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
554 |
|
|
555 |
private boolean isPermittedDo(int angle)
|
|
556 |
{
|
|
557 |
for(int corner=0; corner<8; corner++)
|
|
558 |
{
|
|
559 |
if( !cornerIsUp(corner) )
|
|
560 |
{
|
|
561 |
int currQuat = mCornerQuat[corner];
|
|
562 |
int finalQuat= QUAT_MULT[angle][currQuat];
|
|
563 |
if( quatIsBad(finalQuat,corner) ) return false;
|
|
564 |
}
|
|
565 |
}
|
|
566 |
|
|
567 |
return true;
|
|
568 |
}
|
|
569 |
|
|
570 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
571 |
|
|
572 |
private boolean isPermittedUp(int angle)
|
|
573 |
{
|
|
574 |
for(int corner=0; corner<8; corner++)
|
|
575 |
{
|
|
576 |
//android.util.Log.e("D", "isPermittedUp: up corner: "+corner+" angle: "+angle);
|
|
577 |
|
|
578 |
|
|
579 |
if( cornerIsUp(corner) )
|
|
580 |
{
|
|
581 |
int currQuat = mCornerQuat[corner];
|
|
582 |
int finalQuat= QUAT_MULT[angle][currQuat];
|
|
583 |
|
|
584 |
//boolean bad = quatIsBad(finalQuat,corner);
|
|
585 |
//android.util.Log.e("D", "isPermittedUp: up corner: "+corner+" angle: "+angle+" is bad: "+bad);
|
|
586 |
|
|
587 |
if( quatIsBad(finalQuat,corner) ) return false;
|
|
588 |
}
|
|
589 |
}
|
|
590 |
|
|
591 |
return true;
|
|
592 |
}
|
|
593 |
|
|
594 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
595 |
|
|
596 |
private void computePermittedAngles()
|
|
597 |
{
|
|
598 |
mPermittedDo = 0;
|
|
599 |
|
|
600 |
for(int angle=0; angle<BASIC_ANGLE[0]; angle++)
|
|
601 |
{
|
|
602 |
if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
|
|
603 |
}
|
|
604 |
|
|
605 |
mPermittedUp = 0;
|
|
606 |
|
|
607 |
for(int angle=0; angle<BASIC_ANGLE[0]; angle++)
|
|
608 |
{
|
|
609 |
if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
|
|
610 |
}
|
|
611 |
/*
|
|
612 |
String strDo="";
|
|
613 |
|
|
614 |
for(int i=0; i<mPermittedDo; i++)
|
|
615 |
{
|
|
616 |
strDo += (" "+mPermittedAngles[0][i]);
|
|
617 |
}
|
|
618 |
|
|
619 |
String strUp="";
|
|
620 |
|
|
621 |
for(int i=0; i<mPermittedUp; i++)
|
|
622 |
{
|
|
623 |
strUp += (" "+mPermittedAngles[1][i]);
|
|
624 |
}
|
|
625 |
|
|
626 |
android.util.Log.e("D", "up : "+strUp);
|
|
627 |
android.util.Log.e("D", "down: "+strDo);
|
|
628 |
|
|
629 |
*/
|
|
630 |
}
|
|
631 |
|
|
632 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
633 |
|
|
634 |
private int getNextAngle(Random rnd, int layer)
|
|
635 |
{
|
|
636 |
int basic = BASIC_ANGLE[0];
|
|
637 |
int num = layer==0 ? mPermittedDo:mPermittedUp;
|
|
638 |
int index = rnd.nextInt(num);
|
|
639 |
int angle = mPermittedAngles[layer][index];
|
|
640 |
return angle<basic/2 ? -angle : basic-angle;
|
|
641 |
}
|
|
642 |
|
|
643 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
644 |
|
|
645 |
private int getNextAngleNotZero(Random rnd, int layer)
|
|
646 |
{
|
|
647 |
int basic = BASIC_ANGLE[0];
|
|
648 |
int num = layer==0 ? mPermittedDo:mPermittedUp;
|
|
649 |
int index = rnd.nextInt(num-1);
|
|
650 |
int angle = mPermittedAngles[layer][index+1];
|
|
651 |
return angle<basic/2 ? -angle : basic-angle;
|
|
652 |
}
|
|
653 |
|
|
654 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
655 |
|
|
656 |
private int makeQuat(int axis,int index)
|
|
657 |
{
|
|
658 |
if( axis==1 ) return 13;
|
|
659 |
if( index<0 ) index+=12;
|
|
660 |
return index;
|
|
661 |
}
|
|
662 |
|
|
663 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
664 |
|
|
665 |
private boolean cornerBelongs(int index, int axis, int layer)
|
|
666 |
{
|
|
667 |
if( axis==0 )
|
|
668 |
{
|
|
669 |
boolean up = cornerIsUp(index);
|
|
670 |
return ((up && layer==2) || (!up && layer==0));
|
|
671 |
}
|
|
672 |
else
|
|
673 |
{
|
|
674 |
boolean le = cornerIsLeft(index);
|
|
675 |
return ((le && layer==0) || (!le && layer==1));
|
|
676 |
}
|
|
677 |
}
|
|
678 |
|
|
679 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
680 |
|
|
681 |
private void updateCornerQuats(int[] rotInfo)
|
|
682 |
{
|
|
683 |
int axis = rotInfo[0];
|
|
684 |
int layer= rotInfo[1];
|
|
685 |
int index=-rotInfo[2];
|
|
686 |
|
|
687 |
int quat = makeQuat(axis,index);
|
|
688 |
|
|
689 |
for(int corner=0; corner<8; corner++)
|
|
690 |
{
|
|
691 |
if( cornerBelongs(corner,axis,layer) )
|
|
692 |
{
|
|
693 |
int curr = mCornerQuat[corner];
|
|
694 |
mCornerQuat[corner] = QUAT_MULT[quat][curr];
|
|
695 |
}
|
|
696 |
}
|
|
697 |
/*
|
|
698 |
String q="";
|
|
699 |
|
|
700 |
for(int c=0; c<8; c++)
|
|
701 |
{
|
|
702 |
q += (" "+mCornerQuat[c]);
|
|
703 |
}
|
|
704 |
|
|
705 |
android.util.Log.d("D", "quat="+quat+" corner quats now= "+q);
|
|
706 |
*/
|
|
707 |
}
|
|
708 |
|
506 |
709 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
507 |
710 |
// PUBLIC API
|
508 |
711 |
|
... | ... | |
519 |
722 |
}
|
520 |
723 |
|
521 |
724 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
522 |
|
// TODO
|
523 |
725 |
|
524 |
726 |
public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
|
525 |
727 |
{
|
|
728 |
int layer, nextAngle;
|
|
729 |
|
526 |
730 |
if( num==0 )
|
527 |
731 |
{
|
528 |
|
scramble[num][0] = rnd.nextInt(NUM_AXIS);
|
|
732 |
for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
|
|
733 |
mLastRot = rnd.nextInt(4);
|
|
734 |
computePermittedAngles();
|
529 |
735 |
}
|
530 |
|
else
|
531 |
|
{
|
532 |
|
int newVector = rnd.nextInt(NUM_AXIS-1);
|
533 |
|
scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
|
534 |
|
}
|
535 |
|
|
536 |
|
scramble[num][1] = rnd.nextFloat()<=0.5f ? 0 : 1;
|
537 |
736 |
|
538 |
|
switch( rnd.nextInt(4) )
|
|
737 |
switch(mLastRot)
|
539 |
738 |
{
|
540 |
|
case 0: scramble[num][2] = -2; break;
|
541 |
|
case 1: scramble[num][2] = -1; break;
|
542 |
|
case 2: scramble[num][2] = 1; break;
|
543 |
|
case 3: scramble[num][2] = 2; break;
|
|
739 |
case LAST_SL: layer = rnd.nextInt(2);
|
|
740 |
nextAngle = getNextAngle(rnd,layer);
|
|
741 |
|
|
742 |
if( nextAngle==0 )
|
|
743 |
{
|
|
744 |
layer = 1-layer;
|
|
745 |
nextAngle = getNextAngleNotZero(rnd,layer);
|
|
746 |
}
|
|
747 |
|
|
748 |
scramble[num][0] = 0;
|
|
749 |
scramble[num][1] = 2*layer;
|
|
750 |
scramble[num][2] = nextAngle;
|
|
751 |
mLastRot = layer==0 ? LAST_LO : LAST_UP;
|
|
752 |
updateCornerQuats(scramble[num]);
|
|
753 |
|
|
754 |
//android.util.Log.e("D", "SL axis="+scramble[num][0]+" layer="+scramble[num][1]+" angle="+scramble[num][2]);
|
|
755 |
|
|
756 |
break;
|
|
757 |
case LAST_LO:
|
|
758 |
case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
|
|
759 |
nextAngle = getNextAngle(rnd,layer);
|
|
760 |
|
|
761 |
if( nextAngle!=0 )
|
|
762 |
{
|
|
763 |
scramble[num][0] = 0;
|
|
764 |
scramble[num][1] = 2*layer;
|
|
765 |
scramble[num][2] = nextAngle;
|
|
766 |
updateCornerQuats(scramble[num]);
|
|
767 |
mLastRot = LAST_UL;
|
|
768 |
//android.util.Log.e("D", "LO/UP 1 axis="+scramble[num][0]+" layer="+scramble[num][1]+" angle="+scramble[num][2]);
|
|
769 |
}
|
|
770 |
else
|
|
771 |
{
|
|
772 |
scramble[num][0] = 1;
|
|
773 |
scramble[num][1] = rnd.nextInt(2);
|
|
774 |
scramble[num][2] = 1;
|
|
775 |
mLastRot = LAST_SL;
|
|
776 |
updateCornerQuats(scramble[num]);
|
|
777 |
computePermittedAngles();
|
|
778 |
//android.util.Log.e("D", "LO/UP 2 axis="+scramble[num][0]+" layer="+scramble[num][1]+" angle="+scramble[num][2]);
|
|
779 |
}
|
|
780 |
|
|
781 |
break;
|
|
782 |
case LAST_UL: scramble[num][0] = 1;
|
|
783 |
scramble[num][1] = rnd.nextInt(2);
|
|
784 |
scramble[num][2] = 1;
|
|
785 |
mLastRot = LAST_SL;
|
|
786 |
updateCornerQuats(scramble[num]);
|
|
787 |
computePermittedAngles();
|
|
788 |
//android.util.Log.e("D", "UL axis="+scramble[num][0]+" layer="+scramble[num][1]+" angle="+scramble[num][2]);
|
|
789 |
|
|
790 |
break;
|
544 |
791 |
}
|
545 |
792 |
}
|
546 |
793 |
|
Square-1: looks to be finished.