001: #include <assert.h>
002: #include <string.h>
003: #include <stdlib.h>
004: 
005: #include "Point.h"
006: #include "Piece.h"
007: 
008: 
009: 
010: CPiece::CPiece(int NumberOfCubes, int *Coordinates)
011: {
012:         int i;
013: 
014:         TotalNumRotations = 0;
015:         NumCubes = NumberOfCubes;
016:         pRotation = new CPoint[NumberOfCubes];
017: 
018:         for (i = 0; i < NumberOfCubes; i++)
019:         {
020:                 pRotation[i].x = Coordinates[i*3];
021:                 pRotation[i].y = Coordinates[i*3+1];
022:                 pRotation[i].z = Coordinates[i*3+2];
023:         }
024:         SetNumRotations(1);
025:         SortCubes(&(pRotation[0]));
026: 
027:         for (i = 0; i < 3*4*5; i++) 
028:         {
029:                 NumRotationsXYZ[i] = 0;
030:                 pRotationListXYZ[i] = new int[24];
031:         }
032: }
033: 
034: 
035: 
036: CPiece::~CPiece()
037: {
038:         for (int i = 0; i < 3*4*5; i++) delete[] pRotationListXYZ[i];
039:         delete []pRotation;
040: }
041: 
042: 
043: 
044: static int compare( const void *arg1, const void *arg2 )
045: {
046:         CPoint *p1 = (CPoint*)arg1;
047:         CPoint *p2 = (CPoint*)arg2;
048:         int adr1 = (p1->x) + (p1->y)*256 + (p1->z)*65536;
049:         int adr2 = (p2->x) + (p2->y)*256 + (p2->z)*65536;
050:         return adr1 - adr2;
051: }
052: 
053: 
054: 
055: void CPiece::SortCubes(CPoint *pCubes)
056: {
057:         // we sort the cubes so that the first one has the lowest z,y,x

058:         qsort(pCubes,GetNumCubes(),sizeof(CPoint),compare);
059: }
060: 
061: 
062: 
063: bool CPiece::Compare(CPoint *p1, CPoint *p2)
064: {
065:         for (int i = 0; i < GetNumCubes(); i++)
066:         {
067:                 if ( (p1[i].x != p2[i].x) || (p1[i].y != p2[i].y) || (p1[i].z != p2[i].z) )
068:                         return false;
069:         }
070:         return true;
071: }
072: 
073: 
074: 
075: void CPiece::AddRotation(CPoint *pNewRotation)
076: {
077:         for (int i = 0; i < GetNumRotations(); i++)
078:         {
079:                 if (Compare(pNewRotation,&(pRotation[i*GetNumCubes()]))) return;
080:         }
081:         CPoint *pNewMem = new CPoint[(GetNumRotations()+1)*GetNumCubes()];
082:         memcpy(pNewMem,pRotation,sizeof(CPoint)*GetNumRotations()*GetNumCubes());
083:         delete[] pRotation;
084:         pRotation = pNewMem;
085:         for (i = 0; i < GetNumCubes(); i++)
086:         {
087:                 pRotation[GetNumRotations()*GetNumCubes()+i] = pNewRotation[i];
088:         }
089:         SetNumRotations(GetNumRotations()+1);
090: }
091: 
092: 
093: 
094: void CPiece::CreateRotations()
095: {
096:         int i;
097:         CPoint *pNewRotation = new CPoint[GetNumCubes()];
098: 
099:         for (int wz = 0; wz <= 270; wz += 90)
100:         {
101:                 for (int wy = 0; wy <= 270; wy += 90)
102:                 {
103:                         for (int wx = 0; wx <= 270; wx += 90)
104:                         {
105:                                 for (i = 0; i < GetNumCubes(); i++)
106:                                 {
107:                                         pNewRotation[i] = pRotation[i];
108:                                         pNewRotation[i].Rotate(wx,wy,wz,0.0f,0.0f,0.0f);
109:                                 }
110:                                 SortCubes(pNewRotation);
111:                                 CPoint FirstPoint = pNewRotation[0];
112:                                 for (i = 0; i < GetNumCubes(); i++)
113:                                 {
114:                                         pNewRotation[i].x -= FirstPoint.x;
115:                                         pNewRotation[i].y -= FirstPoint.y;
116:                                         pNewRotation[i].z -= FirstPoint.z;
117:                                 }
118:                                 AddRotation(pNewRotation);
119:                         }
120:                 }
121:         }
122:         delete[]pNewRotation;
123: }
124: 
125: 
126: 
127: inline bool CPiece::BoxFit(int x, int y, int z, int rot)
128: {
129:         CPoint* point;
130: 
131:         for (int cube = 0; cube < GetNumCubes(); cube++)
132:         {
133:                 point = GetRotation(rot,cube);
134:                 if ( (point->x+x < 0) || (point->x+x > 2) ||
135:                          (point->y+y < 0) || (point->y+y > 3) ||
136:                          (point->z+z < 0) || (point->z+z > 4) ) return false;
137:         }
138:         return true;
139: }
140: 
141: 
142: 
143: void CPiece::CreateTranslations()
144: {
145:         int adr = 0;
146:         for (int z = 0; z <= 4; z++)
147:         {
148:                 for (int y = 0; y <= 3; y++)
149:                 {
150:                         for (int x = 0; x <= 2; x++)
151:                         {
152:                                 for (int rot = 0; rot < GetNumRotations(); rot++)
153:                                 {
154:                                         if (BoxFit(x,y,z,rot))
155:                                         {
156:                                                 int *p = pRotationListXYZ[adr];
157:                                                 p[NumRotationsXYZ[adr]] = rot;
158:                                                 NumRotationsXYZ[adr]++;
159:                                         }
160:                                 }
161:                                 TotalNumRotations += NumRotationsXYZ[adr];
162:                                 adr++;
163:                         }
164:                 }
165:         }
166: }
167: 
168: 
169: void CPiece::DeleteRotation(int index, int adr)
170: {
171:         if(NumRotationsXYZ[adr] == 0) return;
172:         int *p = pRotationListXYZ[adr];
173:         int Last = p[NumRotationsXYZ[adr] -1];
174:         p[index] = Last;
175:         assert(NumRotationsXYZ[adr] >= 1);
176:         NumRotationsXYZ[adr]--;
177: }
178: 
179: 
180: 
181: bool CPiece::GetDegeneration(int i, int adr)
182: {
183:         int *p = pRotationListXYZ[adr];
184:         return ((p[i] & 256) != 0);
185: }
186: 
187: 
188: 
189: void CPiece::SymmetryElimination()
190: {
191:         for (int z = 0; z <= 4; z++)
192:         {
193:                 for (int y = 0; y <= 3; y++)
194:                 {
195:                         for (int x = 0; x <= 2; x++)
196:                         {
197:                                 for (int i = 0; i < GetNumRotationsXYZ(x+y*3+z*12); i++)
198:                                 {
199:                                         int rot = GetRotationNumber(i,x+y*3+z*12);
200:                                         if (CheckRotation(rot,x,y,z))
201:                                         {
202:                                                 int adr = x + y*3 + z*12;
203:                                                 int *p = pRotationListXYZ[adr];
204:                                                 p[i] |= 256;
205:                                         }
206:                                 }
207:                         }
208:                 }
209:         }
210: }
211: 
212: 
213: bool CPiece::CheckRotation(int rot, int x, int y, int z)
214: {
215:         int i, j;
216:         CPoint *pNewRotation = new CPoint[GetNumCubes()];
217:         CPoint *pLocalRotation = new CPoint[GetNumCubes()];
218:         bool degeneration = false;
219: 
220:         for (int omega = 1; omega <= 3; omega++)
221:         {
222:                 int wx = (omega & 1) * 180;
223:                 int wz = (omega >> 1) * 180;
224:                 for (i = 0; i < GetNumCubes(); i++)
225:                 {
226:                         pNewRotation[i] = pRotation[rot*GetNumCubes() + i];
227:                         pNewRotation[i].x += x;
228:                         pNewRotation[i].y += y;
229:                         pNewRotation[i].z += z;
230:                         pNewRotation[i].Rotate(wx, 0, wz, 1.0f, 1.5f, 2.0f);
231:                         pLocalRotation[i] = pRotation[rot*GetNumCubes() + i];
232:                         pLocalRotation[i].x += x;
233:                         pLocalRotation[i].y += y;
234:                         pLocalRotation[i].z += z;
235:                 }
236:                 SortCubes(pNewRotation);
237:                 if (Compare(pNewRotation,pLocalRotation)) degeneration = true;
238:                 else
239:                 {
240:                         CPoint firstpoint = pNewRotation[0];
241:                         for (i = 0; i < GetNumRotationsXYZ(firstpoint.x+firstpoint.y*3+firstpoint.z*12); i++)
242:                         {
243:                                 int r2 = GetRotationNumber(i, firstpoint.x+firstpoint.y*3+firstpoint.z*12);
244:                                 for (j = 0; j < GetNumCubes(); j++)
245:                                 {
246:                                         pLocalRotation[j] = pRotation[GetNumCubes()*r2 + j];
247:                                         pLocalRotation[j].x += firstpoint.x;
248:                                         pLocalRotation[j].y += firstpoint.y;
249:                                         pLocalRotation[j].z += firstpoint.z;
250:                                 }
251:                                 if ( Compare(pNewRotation, pLocalRotation) )
252:                                         DeleteRotation(i, firstpoint.x+firstpoint.y*3+firstpoint.z*12);
253:                         }
254:                 }
255:         }
256: 
257:         delete[]pLocalRotation;
258:         delete[]pNewRotation;
259: 
260:         return degeneration;
261: }
262: 
263: 
264: unsigned __int64 CPiece::GetRotation64(int index, int adr)
265: {
266:         unsigned __int64 result = 0, eins = 1;
267:         CPoint *point;
268:         int lin, cube, r;
269: 
270:         r = GetRotationNumber(index,adr);
271: 
272:         for (cube = 0; cube < GetNumCubes(); cube++)
273:         {
274:                 point = GetRotation(r,cube);
275:                 lin = adr + point->x + point->y*3 + point->z*12;
276:                 result |= (eins << lin);
277:         }
278:         return result;
279: }