@@ -663,12 +663,14 @@ private void rebuildRotationOverview(PieceType pieceType) {
663663 return ;
664664 }
665665
666+ java .util .HashSet <Integer > duplicateIndices = getDuplicateRotationIndices (pieceType );
666667 rotationOverviewTable .defaults ().pad (4 );
667668 for (int i = 0 ; i < pieceType .rotationSet .size (); i ++) {
668669 final int rotationIndex = i ;
669670 final Piece .Rotation rotation = pieceType .rotationSet .get (i );
670671 String prefix = (rotationIndex == selectedRotationIndex ) ? "> " : "" ;
671- TextButton button = new TextButton (prefix + "R" + rotationIndex + " (" + getFilledCellCount (rotation ) + ", " + getRotationBoundingBox (rotation ) + ")" , engine .uiSkin );
672+ String duplicateLabel = duplicateIndices .contains (rotationIndex ) ? ", dup" : "" ;
673+ TextButton button = new TextButton (prefix + "R" + rotationIndex + " (" + getFilledCellCount (rotation ) + ", " + getRotationBoundingBox (rotation ) + duplicateLabel + ")" , engine .uiSkin );
672674 button .addListener (new ClickListener () {
673675 @ Override
674676 public void clicked (InputEvent event , float x , float y ) {
@@ -712,6 +714,51 @@ private String getRotationBoundingBox(Piece.Rotation rotation) {
712714 return (maxX - minX + 1 ) + "x" + (maxY - minY + 1 );
713715 }
714716
717+ private String getRotationSymmetry (Piece .Rotation rotation ) {
718+ if (rotation == null || rotation .blockOffsets .isEmpty ()) return "none" ;
719+ int minX = Integer .MAX_VALUE ;
720+ int maxX = Integer .MIN_VALUE ;
721+ int minY = Integer .MAX_VALUE ;
722+ int maxY = Integer .MIN_VALUE ;
723+ java .util .HashSet <String > occupied = new java .util .HashSet <String >();
724+ for (Piece .BlockOffset offset : rotation .blockOffsets ) {
725+ minX = Math .min (minX , offset .x );
726+ maxX = Math .max (maxX , offset .x );
727+ minY = Math .min (minY , offset .y );
728+ maxY = Math .max (maxY , offset .y );
729+ occupied .add (offset .x + "," + offset .y );
730+ }
731+
732+ boolean horizontal = true ;
733+ boolean vertical = true ;
734+ for (Piece .BlockOffset offset : rotation .blockOffsets ) {
735+ int mirrorX = maxX - (offset .x - minX );
736+ int mirrorY = maxY - (offset .y - minY );
737+ if (!occupied .contains (mirrorX + "," + offset .y )) horizontal = false ;
738+ if (!occupied .contains (offset .x + "," + mirrorY )) vertical = false ;
739+ }
740+
741+ if (horizontal && vertical ) return "horizontal + vertical" ;
742+ if (horizontal ) return "horizontal" ;
743+ if (vertical ) return "vertical" ;
744+ return "none" ;
745+ }
746+
747+ private java .util .HashSet <Integer > getDuplicateRotationIndices (PieceType pieceType ) {
748+ java .util .HashSet <Integer > duplicates = new java .util .HashSet <Integer >();
749+ if (pieceType == null || pieceType .rotationSet == null ) return duplicates ;
750+ java .util .HashMap <String , Integer > firstSeen = new java .util .HashMap <String , Integer >();
751+ for (int i = 0 ; i < pieceType .rotationSet .size (); i ++) {
752+ String signature = getRotationSignature (pieceType .rotationSet .get (i ));
753+ if (firstSeen .containsKey (signature )) {
754+ duplicates .add (i );
755+ } else {
756+ firstSeen .put (signature , i );
757+ }
758+ }
759+ return duplicates ;
760+ }
761+
715762 private int getUniqueRotationCount (PieceType pieceType ) {
716763 if (pieceType == null || pieceType .rotationSet == null ) return 0 ;
717764 java .util .HashSet <String > signatures = new java .util .HashSet <String >();
@@ -810,6 +857,7 @@ private void refreshEditorState() {
810857 int currentRotationCount = pieceType != null && pieceType .rotationSet != null ? pieceType .rotationSet .size () : 0 ;
811858 int uniqueRotationCount = getUniqueRotationCount (pieceType );
812859 int duplicateRotationCount = Math .max (0 , currentRotationCount - uniqueRotationCount );
860+ String symmetry = getRotationSymmetry (rotation );
813861 summaryLabel .setText (
814862 "Mode: " + currentGameType .gameMode
815863 + " | Grid: " + currentGameType .gridWidth + "x" + currentGameType .gridHeight
@@ -818,6 +866,7 @@ private void refreshEditorState() {
818866 + " | Current piece rotations: " + currentRotationCount
819867 + " | Filled cells in current rotation: " + getFilledCellCount (rotation )
820868 + " | Current bbox: " + getRotationBoundingBox (rotation )
869+ + " | Symmetry: " + symmetry
821870 + " | Unique/duplicate rotations: " + uniqueRotationCount + "/" + duplicateRotationCount
822871 + " | Rules: " + getEnabledRuleSummary ()
823872 );
0 commit comments