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:
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: }