E:\Src\java\netBeans\Puzzle\JTurm\src\jturm\PuzzleShift.java
  1 package jturm;
  2 
  3 /**
  4  *
  5  * @author Rolf
  6  */
  7 public class PuzzleShift {
  8 
  9     Puzzle var[] = new Puzzle[120];     // list of puzzles
 10     int firstBusy[] = new int[120];     // first busy position
 11     boolean isTop[] = new boolean[120];     // is this a top Element
 12     boolean isBottom[] = new boolean[120];     // is this a top Element
 13     int varMax = 0;                     // how many variations we have setup
 14     boolean inUse = false;                // is this puzzle in use
 15     int height;                      // height of the puzzle container
 16 
 17     //--------------------------------------------------------------------------
 18     public PuzzleShift(Puzzle p, int height) {
 19         this.height = height;
 20         Puzzle a = turn(p);
 21 
 22         for (int x = 0; x < 12; x++) {
 23             shift(p);                   // circle around 
 24             if (addP(p)) {
 25                 up(p);                 // shift up
 26             }
 27         }
 28 
 29         if (a != null) {
 30             for (int x = 0; x < 12; x++) {
 31                 shift(a);               // circle around 
 32                 if (addP(a)) {
 33                     up(a);            // shift up
 34                 }
 35             }
 36         }
 37     }
 38     //--------------------------------------------------------------------------
 39 
 40     private Puzzle turn(Puzzle p) {
 41         // try to turn upside down (only needed for outside)
 42 
 43         //  i __out_______ 
 44         //  0 1 2 3 ... 12
 45 
 46         //  . . . X                     input
 47         //  . X X X
 48 
 49 
 50         //  . X X X                     turn result 
 51         //  . X . .
 52 
 53 
 54         for (int x = 0; x < height; x++) {
 55             if ((p.p[x] % 2) == 1) {
 56                 return null;      // this is a inner circle puzzle
 57             }
 58         }
 59 
 60         // find height/width of puzzle
 61         int h = 0;
 62         int w = 0;
 63         for (int x = 0; x < height; x++) {
 64             if (p.p[x] > 0) {
 65                 int ww = (int) (Math.log(p.p[x]) / Math.log(2.0));
 66                 if (ww > w) {
 67                     w = ww;
 68                 }
 69                 h++;
 70             }
 71         }
 72         Puzzle a = new Puzzle(height);
 73         a.c = p.c;
 74 
 75         for (int y = 0; y < h; y++) {
 76             a.p[h - y - 1] = p.invert(y, w);
 77         }
 78         return a;
 79 
 80     }
 81 
 82     //--------------------------------------------------------------------------
 83     private void up(Puzzle p) {
 84         // try to move up by adding 13
 85         //  i __out_______ 
 86         //  0 1 2 3 ... 12
 87         //
 88 
 89 
 90         for (int h = 1; h < height; h++) {
 91             if (p.p[height - h] == 0) {                // upper layer is empty
 92                 Puzzle up = new Puzzle(height);
 93                 up.c = p.c;
 94                 for (int x = height - 1; x + 1 - h > 0; x--) {
 95                     up.p[x] = p.p[x - h];
 96                 }
 97                 addP(up);
 98             }
 99         }
100     }
101     //--------------------------------------------------------------------------
102 
103     private void shift(Puzzle p) {
104         // try to shift around
105 
106         //  i __out_______ 
107         //  0 1 2 3 ... 12
108 
109         //  x . X . X           Start               1+4+4096
110         //
111         //  x X . X .           End                 1+2+8
112         //
113 
114         for (int x = 0; x < height; x++) {
115             short inner = (short) (p.p[x] % 2);
116             short outer = (short) ((p.p[x] - inner) * 2);
117             if (outer >= 8192) {
118                 p.p[x] = (short) (outer % 8192 + 2 + inner);
119             } else {
120                 p.p[x] = (short) (outer % 8192 + inner);
121             }
122         }
123     }
124     //--------------------------------------------------------------------------
125 
126     private boolean addP(Puzzle a) {
127         var[varMax] = new Puzzle(height);
128         if (isNew(a)) {
129 
130             for (int x = 0; x < height; x++) {
131                 var[varMax].p[x] = a.p[x];
132             }
133 
134             var[varMax].c = a.c;
135 
136             firstBusy[varMax] = a.getFirstBusy();
137             isTop[varMax] = (a.getLastBusy() / 13 == height - 1);
138             isBottom[varMax] = (firstBusy[varMax] == 0);
139 
140             varMax++;
141 
142             return true;
143         }
144         return false;
145     }
146     //--------------------------------------------------------------------------
147 
148     private boolean isNew(Puzzle a) {
149         if (a.c == '?') {
150             return false;
151         }
152         for (int x = 0; x < varMax; x++) {
153             if (height == 2 && var[x].p[0] == a.p[0] && var[x].p[1] == a.p[1]) {
154                 return false;
155             }
156             if (height == 3 && var[x].p[0] == a.p[0] && var[x].p[1] == a.p[1] && var[x].p[2] == a.p[2]) {
157                 return false;
158             }
159             if (height == 4 && var[x].p[0] == a.p[0] && var[x].p[1] == a.p[1] && var[x].p[2] == a.p[2] && var[x].p[3] == a.p[3]) {
160                 return false;
161             }
162             if (height == 5 && var[x].p[0] == a.p[0] && var[x].p[1] == a.p[1] && var[x].p[2] == a.p[2] && var[x].p[3] == a.p[3] && var[x].p[4] == a.p[4]) {
163                 return false;
164             }
165         }
166         return true;
167     }
168 }
169