001: /*
002: 
003:   File: Piece.cpp
004: 
005:   (c) 2003 by Oliver Ehli
006: 
007:      This program is free software; you can redistribute it and/or modify
008:      it under the terms of the GNU General Public License as published by
009:      the Free Software Foundation; either version 2 of the License, or
010:      (at your option) any later version.
011: 
012:      This program is distributed in the hope that it will be useful,
013:      but WITHOUT ANY WARRANTY; without even the implied warranty of
014:      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015:      GNU General Public License for more details.
016: 
017:      You should have received a copy of the GNU General Public License
018:      along with this program; if not, write to the Free Software
019:      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
020: 
021:      See File LICENSE for more Information.
022: 
023: */
024: #include <string.h>
025: #include <fstream.h>
026: #include "Piece.h"
027: #include "InventorWriter.h"
028: 
029: 
030: long long Piece::mask = (1ll << PC_X_DIM) - 1ll;
031: 
032: Piece::Piece(int inId, int (*dimensions)[3], bool (*description)[PC_Z_DIM][PC_Y_DIM][PC_X_DIM],
033:              bool skipSymmetry, bool specialSymmetry) : numPositions(0), numRotations(1)
034: {
035:   _bbox = dimensions;
036:   _cubes = description;
037: 
038:   id = inId;
039: 
040:   piece = 0;
041: 
042:   for (int i=0; i<GC_X_DIM; i++)
043:     for (int j=0; j<GC_Y_DIM; j++)
044:       for (int k=0; k<GC_Z_DIM; k++) {
045:         if(i>=(*_bbox)[2] || j>=(*_bbox)[1] || k>=(*_bbox)[0]) continue;
046:         if((*_cubes)[i][j][k])
047:           piece |= ((1ll << ((k * GC_Y_DIM + j) * GC_X_DIM)) << i);
048:       }
049: 
050:   int tmp = (*_bbox)[0];
051:   (*_bbox)[0] = (*_bbox)[2];
052:   (*_bbox)[2] = tmp;
053: 
054:   rotations[0] = piece;
055:   rotatedBBoxes = new int*[MAX_NUM_ROT];
056:   rotatedBBoxes[0] = *dimensions;
057: 
058:   buildRotations();
059:   buildPositions(skipSymmetry, specialSymmetry);
060: 
061:   for (int i=0; i<GC_X_DIM*GC_Y_DIM*GC_Z_DIM; i++)
062:     occupiedCoordsIndex[i] = 0;
063:   buildOuccupanceInfo();
064: 
065: }
066: 
067: 
068: long long Piece::addRotation(long long rotatedPiece, int* rotatedBBox)
069: {
070:   int i;
071:   for (i=0; i< numRotations; i++)
072:     if (rotations[i] == rotatedPiece) break;
073:   
074:   if(i==numRotations) {
075:     rotations[i] = rotatedPiece;
076:     rotatedBBoxes[i] = rotatedBBox;
077:     numRotations++;
078:   }
079: 
080:   return rotatedPiece;
081: }
082: 
083: 
084: void Piece::buildRotations()
085: {
086:   long long current  = piece;
087: 
088:   for(int i=1; i<4; i++) {
089:     int *tmpXBBox = new int[3];
090: 
091:     tmpXBBox[0] = (*_bbox)[0];
092:     tmpXBBox[1] = (*_bbox)[2];
093:     tmpXBBox[2] = (*_bbox)[1];
094: 
095:     if((i%2 && tmpXBBox[1]>GC_Y_DIM) || (i%2 && tmpXBBox[2]>GC_Z_DIM)) continue;
096:     addRotation(Puzzle::rotate(current, i, 0, 0, *_bbox, mask), (i % 2 ? tmpXBBox : *_bbox));
097:   }
098: 
099:   int nr = numRotations;
100:   for(int i=0; i<nr; i++) {
101:     int *tmpYBBox = new int[3];
102:     tmpYBBox[0] = rotatedBBoxes[i][2];
103:     tmpYBBox[1] = rotatedBBoxes[i][1];
104:     tmpYBBox[2] = rotatedBBoxes[i][0];
105: 
106:     for(int j=1; j<4; j++) {
107:       if((j%2 && tmpYBBox[0]>GC_X_DIM) || (j%2 && tmpYBBox[2]>GC_Z_DIM)) continue;
108:       addRotation(Puzzle::rotate(rotations[i], 0, j, 0, rotatedBBoxes[i], mask),
109:                   (j % 2 ? tmpYBBox : rotatedBBoxes[i]));
110:     }
111:   }
112: 
113:   nr = numRotations;
114:   for(int i=0; i<nr; i++) {
115:     int *tmpZBBox = new int[3];
116:     tmpZBBox[0] = rotatedBBoxes[i][1];
117:     tmpZBBox[1] = rotatedBBoxes[i][0];
118:     tmpZBBox[2] = rotatedBBoxes[i][2];
119: 
120:     for(int j=1; j<4; j++) {
121:       if((j%2 && tmpZBBox[0]>GC_X_DIM) || (j%2 && tmpZBBox[1]>GC_Y_DIM)) continue;
122:       addRotation(Puzzle::rotate(rotations[i], 0, 0, j, rotatedBBoxes[i], mask),
123:                   (j % 2 ? tmpZBBox : rotatedBBoxes[i]));
124:     }
125:   }
126: 
127: }
128: 
129: long long Piece::mirror(long long piece, bool xAxis, bool yAxis, bool zAxis)
130: {
131:   long long result = 0;
132:   long long mask = 0;
133: 
134:   for(int i=0; i<GC_Z_DIM; i++) 
135:     for(int j=0; j<GC_Y_DIM; j++) {
136:       mask = ((long long) 1) << ((i*GC_Y_DIM + j) * GC_X_DIM);
137:       for(int k=0; k<GC_X_DIM; k++, mask <<= 1)
138:         if(piece & mask) {
139:           result |= ((((long long) 1) <<
140:                       (xAxis ? GC_X_DIM-1-k : k)) <<
141:                      (((zAxis ? GC_Z_DIM-1-i : i)*GC_Y_DIM +
142:                        (yAxis ? GC_Y_DIM-1-j : j)) * GC_X_DIM));
143:         }
144:     }
145: 
146:   return result;
147: }
148: 
149: 
150: void Piece::buildPositions(bool skipSymmetry, bool specialSymmetry)
151: {
152: 
153:   if(!specialSymmetry)
154:     for(int l=0; l < GC_Z_DIM; l++) 
155:       for(int k=0; k < GC_Y_DIM; k++) {
156:         int trY = (l*GC_Y_DIM + k) * GC_X_DIM;
157:         for(int j=0; j < GC_X_DIM; j++)
158:           for(int i=0; i< numRotations; i++) {
159:             if (j > GC_X_DIM - rotatedBBoxes[i][0] ||
160:                 k > GC_Y_DIM - rotatedBBoxes[i][1] ||
161:                 l > GC_Z_DIM - rotatedBBoxes[i][2]) continue;
162:             long long nextPiece = ((rotations[i] <<j) << trY);
163:             if(skipSymmetry) {
164:               bool found = false;
165:               for(int pos=0; pos < numPositions; pos++)
166:                 if(positions[pos] == mirror(nextPiece, true, true, false) ||
167:                    positions[pos] == mirror(nextPiece, true, false, true) ||
168:                    positions[pos] == mirror(nextPiece, false, true, true) ||
169:                    positions[pos] == nextPiece)
170:                   found = true;
171:               if(found) continue;
172:             }
173:             positions[numPositions] = nextPiece;
174:             positionRotation[numPositions] = i;
175:             numPositions++;
176:           }
177:       }
178: 
179:   else
180:     for(int l=GC_Z_DIM-1; l>=0; l--) 
181:       for(int k=GC_Y_DIM-1; k>=0; k--) {
182:         int trY = (l*GC_Y_DIM + k) * GC_X_DIM;
183:         for(int j=GC_X_DIM-1; j>=0; j--)
184:           for(int i=0; i< numRotations; i++) {
185:             if (j > GC_X_DIM - rotatedBBoxes[i][0] ||
186:                 k > GC_Y_DIM - rotatedBBoxes[i][1] ||
187:                 l > GC_Z_DIM - rotatedBBoxes[i][2]) continue;
188:             long long nextPiece = ((rotations[i] <<j) << trY);
189:             {
190:               bool found = false;
191:               for(int pos=0; pos < numPositions; pos++)
192:                 if(positions[pos] == mirror(nextPiece, true, false, true))
193:                   found = true;
194:               if(found) continue;
195:             }
196:             positions[numPositions] = nextPiece;
197:             positionRotation[numPositions] = i;
198:             numPositions++;
199:           }
200:       }
201: }
202:  
203: 
204: 
205: 
206: void Piece::buildOuccupanceInfo()
207: {
208: 
209:   long long mask = 1;
210:   int maxPos = 0;
211: 
212:   for(int j=0; j < GC_Z_DIM; j++)
213:     for(int k=0; k < GC_Y_DIM; k++)
214:       for(int l=0; l < GC_X_DIM; l++, mask <<= 1)
215:         for(int i=0; i<numPositions; i++)
216:           if(positions[i] & mask && !(positions[i] & (mask-1))) {
217: 
218:             int off = (j*GC_Y_DIM + k)*GC_X_DIM + l + 4;
219:             occupiedCoords[off][occupiedCoordsIndex[off]] = positions[i] << 4;
220:             occupiedCoordsPositionIndex[off][occupiedCoordsIndex[off]] = i;
221:             occupiedCoordsIndex[off]++;
222:           }
223: 
224: }
225: 
226: void Piece::dumpPositionInfo()
227: {
228:   cout << "int piece" << id << "NumPositions = " << numPositions << ";" << endl;
229: 
230:   cout << "long long piece" << id << "Positions[" << numPositions << "] = {" << endl << "  ";
231:   for (int i=0; i < numPositions; i++) {
232:     cout << "0x" << hex << positions[i] << ", ";
233:       if(!((i+1)%4)) cout << endl << "  ";
234:   }
235:   cout << dec << endl << "};" << endl;
236: }
237: 
238: 
239: 
240: 
241: void Piece::dumpOuccupanceInfo(bool hi)
242: {
243: 
244:   int start = hi ? 32 : 0;
245:   int stop = hi ? GC_X_DIM*GC_Y_DIM*GC_Z_DIM : 32;
246: 
247:   cout << "   {" << endl;
248:   for (int i=start; i < stop; i++) {
249:     cout << "\t{  ";
250:     for (int j=0; j < occupiedCoordsIndex[i]; j++) {
251:       if(hi)
252:         cout << "0x" << hex << (int)(occupiedCoords[i][j]>>32) << ", ";
253:       else
254:         cout << "0x" << hex << occupiedCoords[i][j] << ", ";
255:       if(!((j+1)%4)) cout << endl << "\t   ";
256:     }
257:     cout << endl << "\t}," << endl;
258:   }
259: 
260:   cout << dec << "   }," << endl << endl << endl;
261: 
262: }
263: 
264: 
265: 
266: 
267: void Piece::dumpOuccupanceIndexInfo(bool hi)
268: {
269:   int start = hi ? 32 : 0;
270:   int stop = hi ? GC_X_DIM*GC_Y_DIM*GC_Z_DIM : 32;
271: 
272:   cout << "   {" << endl;
273: 
274:   for (int i=start; i < stop; i++) {
275:     if(!((i-start)%10)) cout << "     ";
276:     cout << occupiedCoordsIndex[i] << ", ";
277:     if(!((i-start+1)%10)) cout << endl;
278:   }
279:   cout << dec << endl << "   }," << endl << endl;
280: }
281: 
282: 
283: 
284: 
285: // debug-stuff below
286: 
287: #ifdef DEBUG_BIN
288: 
289: void Piece::writeRotatedPiecesAsIV(ofstream & out, const int indentLevel, const int pieceNo)
290: {
291: 
292:   for(int l=0; l<numRotations; l++) {
293:     out << InventorWriter::indent;
294:     out << InventorWriter::beginGroup;
295: 
296:     InventorWriter::writeTranslation(out,
297:                                      l%5 *  7 * InventorWriter::baseUnit,
298:                                      l/5 * -5 * InventorWriter::baseUnit, 0.0);
299: 
300:     InventorWriter::writeBBox(out, indentLevel+1, rotatedBBoxes[l]);
301: 
302:     int m = 0, hiLo = 0;
303:     for (int i=0; i<GC_Z_DIM; i++) {
304:       for (int j=0; j<GC_Y_DIM; j++)
305:         for (int k=0; k<GC_X_DIM; k++, m++)
306:           if(!(rotations[l] & (1ll << m))) continue;
307:           else writeAsIV(out, indentLevel+1, pieceNo, k, j, i);
308:     }
309: 
310:     out << InventorWriter::indent;
311:     out << InventorWriter::endGroup;
312:   }
313: 
314: }
315: 
316: 
317: 
318: void Piece::writePiecePositionsAsIV(ofstream & out, const int indentLevel, const int pieceNo)
319: {
320: 
321:   int bbox[] = { 3, 4, 5 };
322: 
323:   for(int l=0; l<numPositions; l++) {
324:     out << InventorWriter::indent;
325:     out << InventorWriter::beginGroup;
326: 
327:     InventorWriter::writeTranslation(out,
328:                                      l%5 *  7 * InventorWriter::baseUnit,
329:                                      l/5 * -5 * InventorWriter::baseUnit, 0.0);
330: 
331:     InventorWriter::writeBBox(out, indentLevel+1, bbox);
332: 
333:     int m = 0, hiLo = 0;
334:     for (int i=0; i<GC_Z_DIM; i++) {
335:       for (int j=0; j<GC_Y_DIM; j++)
336:         for (int k=0; k<GC_X_DIM; k++, m++) {
337:           if((positions[l] & (1ll << m)))
338:             writeAsIV(out, indentLevel+1, pieceNo, k, j, i);
339:         }
340:     }
341: 
342:     out << InventorWriter::indent;
343:     out << InventorWriter::endGroup;
344:   }
345: 
346: }
347: 
348: 
349: 
350: void Piece::writeDescriptionAsIV(ofstream & out, const int indentLevel, const int pieceNo)
351: {
352:   for (int i=0; i<(*_bbox)[2]; i++)
353:     for (int j=0; j<(*_bbox)[1]; j++)
354:       for (int k=0; k<(*_bbox)[0]; k++)
355:         if(!(*_cubes)[i][j][k]) continue;
356:         else writeAsIV(out, indentLevel, pieceNo, i, j, k);
357: }
358: 
359: 
360: void Piece::writePieceAsIV(ofstream & out, const int indentLevel, const int pieceNo)
361: {
362:   int m = 0, hiLo = 0;
363:   for (int i=0; i<GC_Z_DIM; i++) {
364:     for (int j=0; j<GC_Y_DIM; j++)
365:       for (int k=0; k<GC_X_DIM; k++, m++)
366:         if(!(piece & (1ll << m))) continue;
367:         else writeAsIV(out, indentLevel, pieceNo, i, j, k);
368:   }
369: }
370: 
371: 
372: void Piece::writeAsIV(ofstream & out, const int indentLevel, const int pieceNo,
373:                       const int x, const int y, const int z)
374: {
375: 
376:   for (int l=0; l<indentLevel; l++)
377:     out << InventorWriter::indent;
378:   out << InventorWriter::beginGroup;
379: 
380:   for (int l=0; l<=indentLevel; l++)
381:     out << InventorWriter::indent;
382:     InventorWriter::writeColor(out, pieceNo);
383: 
384:   for (int l=0; l<=indentLevel; l++)
385:     out << InventorWriter::indent;
386:   InventorWriter::writeTranslation(out,
387:                                    x * InventorWriter::baseUnit,
388:                                    y * InventorWriter::baseUnit,
389:                                    z * InventorWriter::baseUnit);
390: 
391:   for (int l=0; l<=indentLevel; l++)
392:     out << InventorWriter::indent;
393:   InventorWriter::writeCube(out);
394: 
395:   for (int l=0; l<indentLevel; l++)
396:     out << InventorWriter::indent;
397:   out << InventorWriter::endGroup;
398: 
399: }
400: 
401: #endif