0001: /////////////////////////////////////////////////////////////////////////////

0002: //Projectname         : 

0003: //Filename                : UKPuzzleCore.cpp 

0004: //Classname                : CUKPuzzleCore

0005: //Author                : Ulrich Kraemer [uk]

0006: //Date                        : 25.03.2003

0007: //Changes                : 

0008: //////////////////////////////////////////////////////////////////////////////

0009: //Synchronization and error handling is not implemenmted yet

0010: 
0011: #include "stdafx.h"
0012: #include "iostream.h"
0013: #include "UKPuzzleCore.h"
0014: #include "math.h"
0015: 
0016: inline long __GETQUICKCHECKINDEX(long* pEnv,long nStartPos,long nDX,long nDY,long nDZ)
0017: {                   
0018:         long QI=0;
0019: 
0020:         long* pEnv2=&pEnv[nStartPos];
0021: 
0022: /*        QI|=        (pEnv2[nDX]?        0x00000001:0L);

0023:         QI|=        (pEnv2[nDY]?        0x00000002:0L);

0024:         QI|=        (pEnv2[nDZ]?        0x00000004:0L);

0025: */
0026:         if (pEnv2[nDX]) QI|=0x01;
0027:         if (pEnv2[nDY]) QI|=0x02;
0028:         if (pEnv2[nDZ]) QI|=0x04;
0029: 
0030:         if (pEnv2[-nDX]) QI|=0x08;
0031:         if (pEnv2[-nDY]) QI|=0x10;
0032:         if (pEnv2[-nDZ]) QI|=0x20;
0033: 
0034:         return QI;
0035: }
0036: 
0037: //for PreCheck2

0038: inline long __GETQUICKCHECKINDEX2(long* pEnv,long nStartPos,long nDX,long nDY,long nDZ)
0039: {                   
0040:         long QI=0;
0041: 
0042:         long* pEnv2=&pEnv[nStartPos];
0043: 
0044: /*

0045:         QI|=        (pEnv2[nDX]?        0x00000001:0L);

0046:         QI|=        (pEnv2[nDY]?        0x00000002:0L);

0047:         QI|=        (pEnv2[nDZ]?        0x00000004:0L);

0048: */
0049: 
0050:         if (pEnv2[nDX]) QI|=0x01;
0051:         if (pEnv2[nDY]) QI|=0x02;
0052:         if (pEnv2[nDZ]) QI|=0x04;
0053: 
0054:         if (pEnv2[-nDX]) QI|=0x08;
0055:         if (pEnv2[-nDY]) QI|=0x10;
0056:         if (pEnv2[-nDZ]) QI|=0x20;
0057: 
0058:         switch (QI)
0059:         {
0060:                 case 0x3e:
0061:                         if (pEnv2[nDX+nDX] &&
0062:                                 pEnv2[nDX+nDY] &&
0063:                                 pEnv2[nDX-nDY] &&
0064:                                 pEnv2[nDX+nDZ] &&
0065:                                 pEnv2[nDX-nDZ])
0066:                         {
0067:                                 QI|=0x01;
0068:                         }
0069:                         break;
0070:                 case 0x3d:
0071:                         if (pEnv2[nDY+nDY] &&
0072:                                 pEnv2[nDY+nDX] &&
0073:                                 pEnv2[nDY-nDX] &&
0074:                                 pEnv2[nDY+nDZ] &&
0075:                                 pEnv2[nDY-nDZ])
0076:                         {
0077:                                 QI|=0x02;
0078:                         }
0079:                         break;
0080:                 case 0x3b:
0081:                         if (pEnv2[nDZ+nDZ] &&
0082:                                 pEnv2[nDZ+nDY] &&
0083:                                 pEnv2[nDZ-nDY] &&
0084:                                 pEnv2[nDZ+nDX] &&
0085:                                 pEnv2[nDZ-nDX])
0086:                         {
0087:                                 QI|=0x04;
0088:                         }
0089:                         break;
0090:                 case 0x37:
0091:                         if (pEnv2[-nDX-nDX] &&
0092:                                 pEnv2[-nDX+nDY] &&
0093:                                 pEnv2[-nDX-nDY] &&
0094:                                 pEnv2[-nDX+nDZ] &&
0095:                                 pEnv2[-nDX-nDZ])
0096:                         {
0097:                                 QI|=0x08;
0098:                         }
0099:                         break;
0100:                 case 0x2f:
0101:                         if (pEnv2[-nDY-nDY] &&
0102:                                 pEnv2[-nDY+nDX] &&
0103:                                 pEnv2[-nDY-nDX] &&
0104:                                 pEnv2[-nDY+nDZ] &&
0105:                                 pEnv2[-nDY-nDZ])
0106:                         {
0107:                                 QI|=0x10;
0108:                         }
0109:                         break;
0110:                 case 0x1f:
0111:                         if (pEnv2[-nDZ-nDZ] &&
0112:                                 pEnv2[-nDZ+nDY] &&
0113:                                 pEnv2[-nDZ-nDY] &&
0114:                                 pEnv2[-nDZ+nDX] &&
0115:                                 pEnv2[-nDZ-nDX])
0116:                         {
0117:                                 QI|=0x20;
0118:                         }
0119:                         break;
0120:         }
0121:         return QI;
0122: }
0123: 
0124: /////////////////////////////////////////////////////////

0125: /////////////////////////////////////////////////////////

0126: // class CUKStone

0127: /////////////////////////////////////////////////////////

0128: /////////////////////////////////////////////////////////

0129: 
0130: CUKStone::CUKStone()
0131: :m_nMaxVariations(0),
0132:  m_pCubes(0)
0133: {
0134: }
0135: CUKStone::~CUKStone()
0136: {
0137:         SetStone(NULL,0,0,0,0,0,NULL);
0138: }
0139: 
0140: BOOL CUKStone::SetStone(
0141:         SUKPuzzlePos* pStone,long nCubeCount,
0142:         long nDX,long nDY,long nDZ,
0143:         long nPosition,long* pBlock)
0144: {
0145:         int i,j,k,l;
0146:         if (m_pCubes)
0147:         {
0148:                 for (i=0;i<m_nMaxVariations;i++)
0149:                 {
0150:                         if (m_pCubes[i])
0151:                                 delete m_pCubes[i];
0152:                         m_pCubes[i]=NULL;
0153:                 }
0154:                 delete[] m_pCubes;
0155:         }
0156:         m_pCubes=NULL;
0157: 
0158:         m_nMaxVariations=0;
0159:         m_nCubeCount=0;
0160: 
0161:         if (pStone==0 || nCubeCount==0 || pBlock==NULL)
0162:                 return TRUE;
0163: 
0164:         m_nMaxVariations=nCubeCount*24;
0165:         m_nCubeCount=nCubeCount;
0166: 
0167:         m_pCubes=new long* [m_nMaxVariations];
0168:         if (!m_pCubes)
0169:         {
0170:                 SetStone(NULL,0,0,0,0,0,NULL);
0171:                 return FALSE;
0172:         }                
0173:         
0174:         for (i=0;i<m_nMaxVariations;i++)
0175:         {
0176:                 m_pCubes[i]=new long[m_nCubeCount];
0177:                  if (!m_pCubes[i])
0178:                 {
0179:                         SetStone(NULL,0,0,0,0,0,NULL);
0180:                         return FALSE;
0181:                 }
0182:         }
0183: 
0184:         long pCubeSort[CUKPuzzleCore::enMaxCubesPerStone];
0185: 
0186:         SUKPuzzlePos theCube;
0187:         //Fill all variations

0188:         for (i=0;i<m_nMaxVariations;i++)
0189:         {
0190:                 for (j=0;j<m_nCubeCount;j++)
0191:                 {
0192:                         theCube=pStone[j];
0193:                         theCube-=pStone[i%m_nCubeCount];
0194: 
0195:                         //rotate stone around x axis

0196:                         switch ((i/m_nCubeCount)%4)
0197:                         {
0198:                                 case 3:theCube.RotateX();//no break;

0199:                                 case 2:theCube.RotateX();//no break;

0200:                                 case 1:theCube.RotateX();//no break;

0201:                                 case 0:;//no break;

0202:                         }
0203:                         //rotate every second stones round 180 Degree around another axis

0204:                         switch ((i/(m_nCubeCount*4))%2)
0205:                         {
0206:                                 case 1:
0207:                                         theCube.RotateZ();
0208:                                         theCube.RotateZ();
0209:                                         break;
0210:                                 case 0:break;
0211:                         }
0212:                         //the one third part around y and one third part around y axis

0213:                         switch (i/(m_nCubeCount*8))
0214:                         {
0215:                                 case 2:theCube.RotateY();break;
0216:                                 case 1:theCube.RotateZ();break;
0217:                                 case 0:break;
0218:                         }
0219:                         //mark invalid stons so that they can be found

0220:                         long nInsertPosition=nPosition+theCube.x*nDX+theCube.y*nDY+theCube.z*nDZ;
0221:                         if (IsInvalid(nInsertPosition,pBlock))//theCube,))

0222:                         {
0223:                                 pCubeSort[j]=-1;
0224:                                 m_pCubes[i][j]=enInvalid;
0225:                         }
0226:                         else
0227:                         {
0228:                                 pCubeSort[j]=GetCubeSortPosition(theCube);
0229:                                 m_pCubes[i][j]=theCube.x*nDX+theCube.y*nDY+theCube.z*nDZ;
0230:                         }
0231:                 }
0232: 
0233:                 //a very dirty bubblesort 

0234:                 for (k=0;k<m_nCubeCount-1;k++)
0235:                         for (l=0;l<m_nCubeCount-1;l++)
0236:                                 if (pCubeSort[l+1]>pCubeSort[l])
0237:                                 {
0238:                                         long nTmp;
0239: 
0240:                                         nTmp=pCubeSort[l+1];
0241:                                         pCubeSort[l+1]=pCubeSort[l];
0242:                                         pCubeSort[l]=nTmp;
0243: 
0244:                                         nTmp=m_pCubes[i][l+1];
0245:                                         m_pCubes[i][l+1]=m_pCubes[i][l];
0246:                                         m_pCubes[i][l]=nTmp;
0247:                                 }
0248:         }
0249: 
0250:         EliminateInvalidStones();
0251:         EliminateDuplicatedStones();
0252:         return TRUE;
0253: }
0254: 
0255: BOOL CUKStone::SetStone(
0256:         CUKStone& rStone,
0257:         long nDX,long nDY,long nDZ,
0258:         long nPosition,long* pBlock)
0259: {
0260:         int i,j;
0261:         if (m_pCubes)
0262:         {
0263:                 for (i=0;i<m_nMaxVariations;i++)
0264:                 {
0265:                         if (m_pCubes[i])
0266:                                 delete m_pCubes[i];
0267:                         m_pCubes[i]=NULL;
0268:                 }
0269:                 delete[] m_pCubes;
0270:         }
0271:         m_pCubes=NULL;
0272: 
0273:         m_nMaxVariations=0;
0274:         m_nCubeCount=0;
0275: 
0276:         if (rStone.m_nCubeCount==0 || pBlock==NULL)
0277:                 return TRUE;
0278: 
0279:         m_nMaxVariations=rStone.m_nMaxVariations;
0280:         m_nCubeCount=rStone.m_nCubeCount;
0281: 
0282:         m_pCubes=new long* [m_nMaxVariations];
0283:         if (!m_pCubes)
0284:         {
0285:                 SetStone(NULL,0,0,0,0,0,NULL);
0286:                 return FALSE;
0287:         }                
0288:         
0289:         for (i=0;i<m_nMaxVariations;i++)
0290:         {
0291:                 m_pCubes[i]=new long[m_nCubeCount];
0292:                  if (!m_pCubes[i])
0293:                 {
0294:                         SetStone(NULL,0,0,0,0,0,NULL);
0295:                         return FALSE;
0296:                 }
0297:         }
0298: 
0299:         //Fill all variations

0300:         for (i=0;i<m_nMaxVariations;i++)
0301:         {
0302:                 for (j=0;j<m_nCubeCount;j++)
0303:                 {
0304:                         long nInsertPosition=nPosition+rStone.m_pCubes[i][j];
0305:                         if (IsInvalid(nInsertPosition,pBlock))//theCube,))

0306:                                 m_pCubes[i][j]=enInvalid;
0307:                         else
0308:                                 m_pCubes[i][j]=rStone.m_pCubes[i][j];
0309:                 }
0310:         }
0311: 
0312:         EliminateInvalidStones();
0313:         //EliminateDuplicatedStones();

0314:         return TRUE;
0315: }
0316: 
0317: long CUKStone::GetCubeSortPosition(SUKPuzzlePos &rStone)
0318: {
0319:         long nResult=0;
0320: 
0321:         double fResult=0;
0322: 
0323:         if (rStone.x<0) fResult+=(pow(-rStone.x,2));
0324:         else                        fResult+=(pow(+rStone.x,2));                        
0325: 
0326:         if (rStone.y<0) fResult+=(pow(-rStone.y,2));
0327:         else                        fResult+=(pow(+rStone.y,2));
0328: 
0329:         if (rStone.z<0) fResult+=(pow(-rStone.z,2));
0330:         else                        fResult+=(pow(+rStone.z,2));
0331: 
0332:         nResult=(long)fResult;
0333: 
0334:         ASSERT(nResult>=0);
0335: 
0336:         return nResult;
0337: }
0338: 
0339: BOOL CUKStone::IsInvalid(long nPosition,long* pBlock)//SUKPuzzlePos &rCube)

0340: {
0341:         //we can no have a negativ value in one axis, if no value in another axis is positiov

0342:         if (pBlock[nPosition]!=0)
0343:                 return TRUE;
0344: 
0345:         return FALSE;
0346: }
0347: 
0348: void CUKStone::EliminateInvalidStones()
0349: {
0350:         int i,j;
0351:         for (i=0;i<m_nMaxVariations;i++)
0352:         {
0353:                 BOOL bInvalid=FALSE;
0354:                 for (j=0;j<m_nCubeCount;j++)
0355:                 {
0356:                         if (m_pCubes[i][j]==enInvalid)
0357:                         {
0358:                                 bInvalid=TRUE;
0359:                                 break;
0360:                         }
0361:                 }
0362:                 if (bInvalid)
0363:                 {
0364:                         for (j=0;j<m_nCubeCount;j++)
0365:                                 m_pCubes[i][j]=m_pCubes[m_nMaxVariations-1][j];
0366: 
0367:                         delete[] m_pCubes[m_nMaxVariations-1];
0368:                 
0369:                         m_nMaxVariations--;
0370:                         i--;
0371:                 }
0372:         }
0373: }
0374: 
0375: void CUKStone::EliminateDuplicatedStones()
0376: {
0377:         for (int i1=0;i1<m_nMaxVariations;i1++)
0378:                 for (int i2=i1+1;i2<m_nMaxVariations;i2++)
0379:                 {
0380:                         BOOL bStoneFound=TRUE;
0381:                         for (int j1=0;j1<m_nCubeCount;j1++)
0382:                         {
0383:                                 BOOL bCubeFound=FALSE;
0384:                                 for (int j2=0;j2<m_nCubeCount;j2++)
0385:                                 {
0386:                                         if (m_pCubes[i1][j1]==m_pCubes[i2][j2])
0387:                                         {
0388:                                                 bCubeFound=TRUE;
0389:                                                 break;
0390:                                         }
0391:                                 }
0392:                                 if (!bCubeFound)
0393:                                 {
0394:                                         bStoneFound=FALSE;
0395:                                         break;
0396:                                 }
0397:                         }
0398:                         if (bStoneFound)
0399:                         {
0400:                                 for (int j=0;j<m_nCubeCount;j++)
0401:                                         m_pCubes[i2][j]=m_pCubes[m_nMaxVariations-1][j];
0402: 
0403:                                 delete[] m_pCubes[m_nMaxVariations-1];
0404: 
0405:                                 m_nMaxVariations--;
0406:                                 i2--;
0407:                         }
0408:                 }
0409: }
0410: 
0411: /////////////////////////////////////////////////////////

0412: /////////////////////////////////////////////////////////

0413: // class CUKPuzzleCore

0414: /////////////////////////////////////////////////////////

0415: /////////////////////////////////////////////////////////

0416: 
0417: CUKPuzzleCore::CUKPuzzleCore(long nFirstStoneOnPos_0,long nLastStoneOnPos_0,LPCTSTR szIniFileName,LPCTSTR szOutputFileName)
0418: :m_nFirstStoneOnPos_0(0),
0419:  m_nLastStoneOnPos_0(0),
0420:  m_nSolutionsFound(0),
0421:  m_bHasFinished(FALSE),
0422:  m_nNextStep(enNextStone),
0423:  m_nXSize(0),
0424:  m_nYSize(0),
0425:  m_nZSize(0),
0426:  m_nEdgeZone(0),
0427:  m_nDX(0),
0428:  m_nDY(0),
0429:  m_nDZ(0),
0430:  m_nPositionCount(0),
0431:  m_nStoneCount(0),
0432:  m_nEntireStoneCount(0),
0433:  m_pBlock(NULL),
0434:  m_pPositions(NULL),
0435:  m_pAvailableStones(NULL),
0436:  m_pUsedStones(NULL),
0437:  m_strIniFileName(szIniFileName),
0438:  m_strOutputFileName(szOutputFileName)
0439:  //m_pBlockPosToPosIndex(NULL)

0440: {
0441:         for (int nQI=0;nQI<enPreDefStones;nQI++)
0442:         {
0443:                 m_ppStones[nQI]=0;
0444:         }
0445: 
0446:         if (nFirstStoneOnPos_0!=-1)
0447:                 m_nFirstStoneOnPos_0=nFirstStoneOnPos_0;
0448: 
0449:         if (nLastStoneOnPos_0!=-1)
0450:                 m_nLastStoneOnPos_0=nLastStoneOnPos_0;
0451: }
0452: 
0453: CUKPuzzleCore::~CUKPuzzleCore()
0454: {
0455:         Deinit();
0456: }
0457: 
0458: /////////////////////////////////////////////////////////

0459: //Tool Functions

0460: void CUKPuzzleCore::WriteOutput(LPCTSTR szFileName)
0461: {
0462:         //write the one every 100 results into a file

0463:         CStdioFile theFile(szFileName,CFile::modeWrite|CFile::shareDenyWrite|CFile::typeText|CFile::modeCreate|CFile::modeNoTruncate);
0464:         theFile.SeekToEnd();
0465: 
0466:         CString strTmp;
0467:         CString strResult;
0468: 
0469:         strResult.Format("Solution : %d\n",m_nSolutionsFound);
0470: 
0471:         if (m_bShowLegend)
0472:         {
0473:                 strResult+="Stone Legend (Presentation=Stone) : ";
0474:                 for (int i=0;i<m_nEntireStoneCount;i++)
0475:                 {
0476:                         if (i==m_nEntireStoneCount-1)
0477:                                 strTmp.Format("%2d=%2d; ",m_ActiveStoneDesc.nStoneID,m_ActiveStoneDesc.nActiveStone);
0478:                         else
0479:                                 strTmp.Format("%2d=%2d; ",m_pUsedStones[i].nStoneID,m_pUsedStones[i].nActiveStone);
0480:                         strResult+=strTmp;
0481:                 }
0482:                 strResult+="\n";
0483:         } 
0484:         strTmp.Format("__BEGINBLOCK[%d]; __XYZ[%d,%d,%d];\n",m_nSolutionsFound,m_nXSize,m_nYSize,m_nZSize);
0485:         strResult+=strTmp;//This is for an eventual result parser

0486:         for (int yPos=m_nYSize+m_nEdgeZone-1;yPos>=m_nEdgeZone;yPos--)//Reverse

0487:         {
0488:                 for (int zPos=m_nEdgeZone;zPos<m_nZSize+m_nEdgeZone;zPos++)
0489:                 {
0490:                         for (int xPos=m_nEdgeZone;xPos<m_nXSize+m_nEdgeZone;xPos++)
0491:                         {
0492:                                 long nPos=xPos*m_nDX+yPos*m_nDY+zPos*m_nDZ;
0493:                                 TCHAR sz[3];
0494:                                 if (m_pBlock[nPos]>99)
0495:                                         sprintf(sz,"--");
0496:                                 else if(m_pBlock[nPos]>0)
0497:                                         sprintf(sz,"%2d",m_pBlock[nPos]);
0498:                                 else
0499:                                         sprintf(sz,"  ");
0500: 
0501:                                 strTmp.Format(" %s ",sz);
0502:                                 for (int i=0;i<m_nSymetriePosCount;i++)
0503:                                         if (nPos==m_SymetriePos[i])
0504:                                         {
0505:                                                 if (i==0)
0506:                                                         strTmp.Format("[%s]",sz);
0507:                                                 else
0508:                                                         strTmp.Format("(%s)",sz);
0509:                                                 break;
0510:                                         }
0511:                                         
0512:                                 strResult+=strTmp;
0513:                         }
0514:                         strResult+="    ";
0515:                 }
0516:                 strResult+="\n";
0517:         }
0518:         strResult+="__ENDBLOCK;\n\n";
0519: 
0520:         //cout << endl << strResult << endl;

0521:         //getchar();

0522:         theFile.WriteString(strResult);
0523:         theFile.Close();
0524: }
0525: void CUKPuzzleCore::SolutionFound()
0526: {
0527:         m_nSolutionsFound++;
0528: 
0529:         //////////////////////////////////////////

0530: #ifdef UKPUZ_WRITEOUTPUT
0531:         //////////////////////////////////////////

0532:         if ((m_nWriteEveryNSolution>0) && (m_nSolutionsFound==1 || m_nSolutionsFound%m_nWriteEveryNSolution==0))
0533:         {
0534:                 WriteOutput(m_strOutputFileName);
0535:         }
0536:         //////////////////////////////////////////

0537: #endif

0538:         //////////////////////////////////////////

0539: 
0540:         return ;
0541: }
0542: 
0543: BOOL CUKPuzzleCore::PreCheck1()
0544: {
0545:         //

0546:         if (m_nUsedStoneCount < m_nFirstPreCheckStone || m_nUsedStoneCount > m_nLastPreCheckStone)
0547:                 return TRUE;
0548:                 
0549:         for (int i=m_ActiveStoneDesc.nPosIndex+1;i<m_nPositionCount;i++)
0550:                 if (m_pBlock[m_pPositions[i]]==0)
0551:                         return (__GETQUICKCHECKINDEX(m_pBlock,m_pPositions[i],m_nDX,m_nDY,m_nDZ)!=0x3f);
0552: 
0553:         return TRUE;
0554: }
0555: 
0556: BOOL CUKPuzzleCore::PreCheck2()
0557: {
0558:         //

0559:         if (m_nUsedStoneCount < m_nFirstPreCheckStone || m_nUsedStoneCount > m_nLastPreCheckStone)
0560:                 return TRUE;
0561:                 
0562:         for (int i=m_ActiveStoneDesc.nPosIndex+1;i<m_nPositionCount;i++)
0563:                 if (m_pBlock[m_pPositions[i]]==0)
0564:                         return (__GETQUICKCHECKINDEX2(m_pBlock,m_pPositions[i],m_nDX,m_nDY,m_nDZ)!=0x3f);
0565: 
0566:         return TRUE;
0567: }
0568: 
0569: 
0570: BOOL CUKPuzzleCore::InsertStone()//Check The Stone Described by the Head of UsedStones List

0571: {
0572:         int i,j;
0573: 
0574:         long nPos;
0575: 
0576:         long nCubeCount=m_ActiveStoneDesc.pStones[m_ActiveStoneDesc.nActiveStone].GetCubeCount();
0577: 
0578:         BOOL bSymetry=FALSE;
0579: 
0580:         long* pCubes=m_ActiveStoneDesc.pStones[m_ActiveStoneDesc.nActiveStone].GetStone(m_ActiveStoneDesc.nVariation);
0581:         long nPosition=m_ActiveStoneDesc.nPosition;
0582: 
0583:         for (i=0;i<nCubeCount;i++)
0584:         {
0585:                 nPos=nPosition+pCubes[i];
0586:                 if (m_pBlock[nPos]!=0)
0587:                         return FALSE;
0588: 
0589:                 if (!bSymetry)
0590:                         for (j=1;j<m_nSymetriePosCount;j++)
0591:                                 if (nPos==m_SymetriePos[j])
0592:                                 {
0593:                                         if (m_ActiveStoneDesc.nActiveStone<m_nFirstActiveStone)                
0594:                                                 return FALSE;
0595:                                         
0596:                                         bSymetry=TRUE;
0597:                                         break;
0598:                                 }
0599:         }                                                        
0600: 
0601:         if (bSymetry)
0602:                 m_nSymetryStonesNeeded--;
0603: 
0604:         if (m_ActiveStoneDesc.nActiveStone>m_nFirstActiveStone)
0605:         {
0606:                 if (m_nSymetryStones<m_nSymetryStonesNeeded)
0607:                 {
0608:                         if (bSymetry)
0609:                                 m_nSymetryStonesNeeded++;
0610:                         return FALSE;
0611:                 }
0612: 
0613:                 m_nSymetryStones--;
0614:         }
0615: 
0616:         for (i=0;i<nCubeCount;i++)
0617:         {
0618:                 nPos=nPosition+pCubes[i];
0619:                 m_pBlock[nPos]=m_ActiveStoneDesc.nStoneID;
0620:         }
0621: 
0622:         //BOOL bRetVal=TRUE;

0623:         switch (m_nPreCheckLevel)
0624:         {
0625:                 case 1:
0626:                         //bRetVal=PreCheck1();

0627:                         return PreCheck1();
0628:                         //break;

0629:                 case 2:
0630:                         //bRetVal=PreCheck2();

0631:                         return PreCheck1();
0632:                         //break;

0633:                 default:
0634:                         return TRUE;
0635:                         //break;

0636:         }
0637:         //if (bRetVal)

0638:         //        m_nTrys++;

0639:         //return bRetVal;

0640: 
0641: }
0642: 
0643: void CUKPuzzleCore::RemoveStone()
0644: {
0645:         long nPosition=m_ActiveStoneDesc.nPosition;
0646:         if (m_pBlock[nPosition]!=m_ActiveStoneDesc.nStoneID)
0647:                 return;
0648: 
0649:         int i,j;
0650: 
0651:         long nPos;
0652: 
0653:         BOOL bSymetry=FALSE;
0654: 
0655:         long nStoneCount=m_ActiveStoneDesc.pStones[m_ActiveStoneDesc.nActiveStone].GetCubeCount();
0656:         long* pCubes=m_ActiveStoneDesc.pStones[m_ActiveStoneDesc.nActiveStone].GetStone(m_ActiveStoneDesc.nVariation);
0657: 
0658:         for (i=0;i<nStoneCount;i++)
0659:         {
0660:                 nPos=nPosition+pCubes[i];
0661:                 
0662:                 if (!bSymetry)
0663:                         for (j=1;j<m_nSymetriePosCount;j++)
0664:                                 if (nPos==m_SymetriePos[j])
0665:                                 {
0666:                                         bSymetry=TRUE;
0667:                                         break;
0668:                                 }
0669: 
0670:                 m_pBlock[nPos]=0;
0671:         }
0672: 
0673:         if (bSymetry)
0674:                 m_nSymetryStonesNeeded++;
0675: 
0676:         if (m_ActiveStoneDesc.nActiveStone>m_nFirstActiveStone)
0677:                 m_nSymetryStones++;
0678: }
0679: 
0680: long CUKPuzzleCore::GetNextFreeStone(long nQuickIndex,long nBeginAfter,long nPosition)
0681: {
0682:         if (m_nUsedStoneCount==0 && nBeginAfter==-1)
0683:                 nBeginAfter=m_nFirstStoneOnPos_0-1;
0684: 
0685:         CUKStone* pStones=m_ppStones[nQuickIndex][nPosition];
0686: 
0687:         if (nBeginAfter<m_nNextFreeStone && pStones[m_nNextFreeStone].GetMaxVariations()>0)
0688:                 return m_nNextFreeStone;
0689:         
0690:         for (int i=nBeginAfter+1;i<m_nStoneCount;i++)
0691:                 if (m_pAvailableStones[i]>0 && pStones[i].GetMaxVariations()>0)
0692:                         return i;                                  
0693: 
0694:         return -1;
0695: }
0696: 
0697: long CUKPuzzleCore::GetNextFreePosIndex()
0698: {
0699:         if (!m_nUsedStoneCount)
0700:                 return 0;
0701: 
0702:         for (int i=m_ActiveStoneDesc.nPosIndex+1;i<m_nPositionCount;i++)
0703:                 if (m_pBlock[m_pPositions[i]]==0)
0704:                         return i;
0705: 
0706:         return -1;
0707: }
0708: 
0709: void CUKPuzzleCore::SetStoneIsUsedFALSE(long nStone)
0710: {
0711:         m_pAvailableStones[nStone]++;
0712: 
0713:         if (m_nNextFreeStone > nStone)
0714:                 m_nNextFreeStone=nStone;
0715: }
0716: 
0717: void CUKPuzzleCore::SetStoneIsUsedTRUE(long nStone)
0718: {
0719:         m_pAvailableStones[nStone]--;
0720:         
0721:         if (m_nNextFreeStone == nStone)
0722:         {
0723:                 m_nNextFreeStone=m_nStoneCount;
0724:                 for (int i=nStone;i<m_nStoneCount;i++)
0725:                         if (m_pAvailableStones[i]>0)
0726:                         {
0727:                                 m_nNextFreeStone=i;
0728:                                 break;
0729:                         }
0730:         }
0731: }
0732: //Tool Functions

0733: /////////////////////////////////////////////////////////

0734: 
0735: //////////////////////////////////////////////////////////

0736: //Basic Evaluation Methodes

0737: void CUKPuzzleCore::TryInsertNextStone()
0738: {
0739:         SUKStoneDesc theStoneDesc;
0740: 
0741: #ifdef UKPUZ_FTL
0742:         do
0743:         {
0744: #endif

0745:                 if (m_nUsedStoneCount==m_nEntireStoneCount)
0746:                 {
0747: 
0748:                         SolutionFound();
0749: 
0750:                         RemoveStone();
0751: 
0752:                         SetStoneIsUsedFALSE(m_ActiveStoneDesc.nActiveStone);
0753:                         m_nUsedStoneCount--;
0754:                         m_ActiveStoneDesc=m_pUsedStones[m_nUsedStoneCount-1];
0755:                         m_nNextStep=enReplaceStone;
0756: 
0757:                         return;
0758:                 }
0759: 
0760:                 theStoneDesc.nVariation=0;
0761:                 theStoneDesc.nPosIndex=GetNextFreePosIndex();
0762:                 theStoneDesc.nPosition=m_pPositions[theStoneDesc.nPosIndex];
0763:                 theStoneDesc.nQuickIndex=__GETQUICKCHECKINDEX(m_pBlock,theStoneDesc.nPosition,m_nDX,m_nDY,m_nDZ);
0764:                 theStoneDesc.nActiveStone=GetNextFreeStone(theStoneDesc.nQuickIndex,-1,theStoneDesc.nPosIndex);
0765:                 theStoneDesc.nStoneID=m_nUsedStoneCount+1;
0766:                 
0767:                 if (theStoneDesc.nActiveStone==-1)
0768:                 {
0769:                         m_nNextStep=enReplaceStone;
0770:                         return;
0771:                 }
0772: 
0773:                 theStoneDesc.pStones=m_ppStones[theStoneDesc.nQuickIndex][theStoneDesc.nPosIndex];
0774: 
0775:                 SetStoneIsUsedTRUE(theStoneDesc.nActiveStone);
0776: 
0777:                 /////////////////////////////////////////////

0778:                 if (m_nUsedStoneCount==0)
0779:                 {
0780:                         m_nFirstActiveStone=theStoneDesc.nActiveStone;
0781: 
0782:                         m_nSymetryStones=m_nEntireStoneCount-1-m_nFirstActiveStone;
0783:                         m_nSymetryStonesNeeded=m_nSymetriePosCount-1;
0784:                 }
0785:                 /////////////////////////////////////////////

0786: 
0787:                 if (m_nUsedStoneCount>0)
0788:                         m_pUsedStones[m_nUsedStoneCount-1]=m_ActiveStoneDesc;
0789: 
0790:                 m_ActiveStoneDesc=theStoneDesc;
0791:                 m_nUsedStoneCount++;
0792: 
0793: #ifdef UKPUZ_FTL
0794:         }
0795:         while (InsertStone());
0796: 
0797:         TryReplaceStone();
0798: #else 
0799:         if (InsertStone())
0800:                 m_nNextStep=enNextStone;
0801:         else
0802:                 m_nNextStep=enReplaceStone;
0803: #endif

0804: }
0805: 
0806: void CUKPuzzleCore::TryReplaceStone()
0807: {
0808: #ifdef UKPUZ_FTL
0809:         do
0810:         {
0811: #endif

0812:                 RemoveStone();
0813:                 m_ActiveStoneDesc.nVariation++;
0814: 
0815:                 while (m_ActiveStoneDesc.nVariation>=m_ActiveStoneDesc.pStones[m_ActiveStoneDesc.nActiveStone].GetMaxVariations())
0816:                 {
0817:                         SetStoneIsUsedFALSE(m_ActiveStoneDesc.nActiveStone);
0818: 
0819:                         m_ActiveStoneDesc.nVariation=0;
0820:                         m_ActiveStoneDesc.nActiveStone=GetNextFreeStone(m_ActiveStoneDesc.nQuickIndex,m_ActiveStoneDesc.nActiveStone,m_ActiveStoneDesc.nPosIndex);
0821: 
0822:                         if (m_ActiveStoneDesc.nActiveStone==-1)
0823:                         {
0824:                                 m_nUsedStoneCount--;
0825:                                 m_nNextStep=enReplaceStone;
0826:                                 
0827:                                 if (m_nUsedStoneCount==0)
0828:                                 {
0829:                                         m_nNextStep=enFinished;
0830:                                         return;
0831:                                 }
0832:                                 else
0833:                                 {
0834:                                         m_ActiveStoneDesc=m_pUsedStones[m_nUsedStoneCount-1];
0835:                                         RemoveStone();
0836:                                         m_ActiveStoneDesc.nVariation++;
0837:                                 }
0838: 
0839:                                 continue;
0840:                         }
0841: 
0842:                         SetStoneIsUsedTRUE(m_ActiveStoneDesc.nActiveStone);
0843: 
0844:                         /////////////////////////////////////////////

0845:                         if (m_nUsedStoneCount==1)
0846:                         {
0847:                                 m_nFirstActiveStone=m_ActiveStoneDesc.nActiveStone;
0848: 
0849:                                 m_nSymetryStones=m_nEntireStoneCount-1-m_nFirstActiveStone;
0850:                                 m_nSymetryStonesNeeded=m_nSymetriePosCount-1;
0851:                         }
0852:                         /////////////////////////////////////////////

0853:                 }
0854: #ifdef UKPUZ_FTL
0855:         }
0856:         while (!InsertStone());
0857:         m_nNextStep=enNextStone;
0858: #else

0859:         if (InsertStone())
0860:                 m_nNextStep=enNextStone;
0861:         else
0862:                 m_nNextStep=enReplaceStone;
0863: #endif

0864: }
0865: //Basic Evaluation Methodes

0866: //////////////////////////////////////////////////////////

0867: 
0868: //////////////////////////////////////////////////////////

0869: //////////////////////////////////////////////////////////

0870: //////////////////////////////////////////////////////////

0871: UKPUZ_STATE CUKPuzzleCore::DoNextStep()
0872: {
0873:         if (!m_bIsInit)
0874:                 return UKPUZ_UNKNOWNERROR;
0875: 
0876:         switch (m_nNextStep)
0877:         {
0878:                 case enNextStone:
0879:                         TryInsertNextStone();
0880:                         break;
0881:                 case enReplaceStone:
0882:                         TryReplaceStone();
0883:                         break;
0884:                 case enFinished:
0885:                         m_bHasFinished=TRUE;
0886:                         break;
0887:         }
0888: 
0889:         if (m_nFirstActiveStone>m_nLastStoneOnPos_0 || m_nFirstActiveStone>m_nStoneCount)
0890:         {
0891:                 m_nNextStep=enFinished;
0892:                 m_bHasFinished=TRUE;
0893:         }
0894: 
0895:         return UKPUZ_NOERROR;
0896: }
0897: //////////////////////////////////////////////////////////

0898: //////////////////////////////////////////////////////////

0899: //////////////////////////////////////////////////////////

0900: 
0901: BOOL CUKPuzzleCore::ReadCoordinate(CUKIniAccess& theFile,LPCTSTR szSection,LPCTSTR szKey,SUKPuzzlePos &rPos)
0902: {
0903:         CLongArray theArray;
0904:         if (!theFile.ReadValue(szSection,szKey,theArray))
0905:                 return FALSE;
0906: 
0907:         if (theArray.GetSize()!=3)
0908:                 return FALSE;
0909: 
0910:         rPos=SUKPuzzlePos(theArray[0],theArray[1],theArray[2]);
0911:         return TRUE;
0912: }
0913: 
0914: BOOL CUKPuzzleCore::ReadStone(CUKIniAccess& theFile,LPCTSTR szSection,LPCTSTR szKey,CUKStone &rStone,long &nStoneCount,long nDX,long nDY,long nDZ,long nPosition,long* pBlock)
0915: {
0916:         CLongArray theArray;
0917:         if (!theFile.ReadValue(szSection,szKey,theArray))
0918:                 return FALSE;
0919: 
0920:         SUKPuzzlePos theCubes[32];//Max 32 Cubes per Stone at the Moment

0921:         if (theArray.GetSize()>(2+32*3) || theArray.GetSize() < 5 || theArray.GetSize() != (theArray[1]*3+2))
0922:                 return FALSE;
0923: 
0924:         for (int i=0;i<theArray[1];i++)
0925:         {
0926:                 theCubes[i].x=theArray[i*3+2];
0927:                 theCubes[i].y=theArray[i*3+3];
0928:                 theCubes[i].z=theArray[i*3+4];
0929:         }
0930:         rStone.SetStone(theCubes,theArray[1],nDX,nDY,nDZ,nPosition,m_pBlock);
0931:         nStoneCount=theArray[0];
0932:         return TRUE;
0933: }
0934: 
0935: //////////////////////////////////////////////////////////

0936: //(De)Init Functions

0937: BOOL CUKPuzzleCore::PreInitBlock()
0938: {
0939:         CUKIniAccess theIniFile(m_strIniFileName);
0940: 
0941:         ASSERT (m_nXSize>0 && m_nYSize>0 && m_nZSize>0 && m_nEdgeZone>0);
0942: 
0943:         m_pBlock=new long[(m_nXSize+2*m_nEdgeZone)*(m_nYSize+2*m_nEdgeZone)*(m_nZSize+2*m_nEdgeZone)];
0944:         if (!m_pBlock)
0945:                 return FALSE;
0946: 
0947:         //m_pBlockPosToPosIndex=new long[(m_nXSize+2*m_nEdgeZone)*(m_nYSize+2*m_nEdgeZone)*(m_nZSize+2*m_nEdgeZone)];

0948:         //if (!m_pBlockPosToPosIndex)

0949:         //        return FALSE;

0950: 
0951:         CLongArray theArray;
0952: 
0953:         for (int zPos=0;zPos<m_nZSize+2*m_nEdgeZone;zPos++)
0954:         {
0955:                 for (int yPos=0;yPos<m_nYSize+2*m_nEdgeZone;yPos++)
0956:                 {
0957:                         if (m_bLoadFromIni &&
0958:                                 zPos>=m_nEdgeZone && zPos<m_nZSize+m_nEdgeZone &&
0959:                                 yPos>=m_nEdgeZone && yPos<m_nYSize+m_nEdgeZone)
0960:                         {
0961:                                 CString strTmp;
0962:                                 strTmp.Format("YZLine_%02d_%02d",yPos-m_nEdgeZone,zPos-m_nEdgeZone);
0963:                                 if (!theIniFile.ReadValue("BlockInfo",strTmp,theArray))
0964:                                         return FALSE;
0965: 
0966:                                 if (theArray.GetSize()!=m_nXSize)
0967:                                         return FALSE;
0968:                         }
0969: 
0970:                         for (int xPos=0;xPos<m_nXSize+2*m_nEdgeZone;xPos++)
0971:                         {                        
0972:                                 if (zPos<m_nEdgeZone || zPos>=m_nZSize+m_nEdgeZone ||
0973:                                         yPos<m_nEdgeZone || yPos>=m_nYSize+m_nEdgeZone ||
0974:                                         xPos<m_nEdgeZone || xPos>=m_nXSize+m_nEdgeZone)
0975:                                         m_pBlock[xPos*m_nDX+yPos*m_nDY+zPos*m_nDZ]=-1;//the Edge Zone

0976:                                 else if (m_bLoadFromIni)
0977:                                         m_pBlock[xPos*m_nDX+yPos*m_nDY+zPos*m_nDZ]=(theArray[xPos-m_nEdgeZone]>0)?theArray[xPos-m_nEdgeZone]:-1;
0978:                                 else
0979:                                         m_pBlock[xPos*m_nDX+yPos*m_nDY+zPos*m_nDZ]=0;//Not Used

0980:                         }
0981:                 }
0982:         }
0983: 
0984:         return TRUE;
0985: }
0986: 
0987: #define __XYZ(X,Y,Z) ((X+m_nEdgeZone)*m_nDX+(Y+m_nEdgeZone)*m_nDY+(Z+m_nEdgeZone)*m_nDZ);
0988: 
0989: BOOL CUKPuzzleCore::InitPositionOrder()
0990: {
0991:         CUKIniAccess theIniFile(m_strIniFileName);
0992: 
0993:         ASSERT(m_nPositionCount>0);
0994: 
0995:         m_pPositions=new long[m_nPositionCount];
0996:         if (!m_pPositions)
0997:                 return FALSE;
0998: 
0999:         CDWordArray arrPositionOrder;
1000:         arrPositionOrder.SetSize(m_nPositionCount);
1001:         if (arrPositionOrder.GetSize()!=m_nPositionCount)
1002:                 return FALSE;
1003: 
1004:         long nPos=0;
1005: 
1006:         if (m_bLoadFromIni)
1007:         {
1008:                 for (int i=0;i<m_nSymetriePosCount;i++)
1009:                 {
1010:                         CString strTmp;
1011:                         strTmp.Format("SymPos%d",i);
1012:                         if (!ReadCoordinate(theIniFile,"SymetryInfo",strTmp,m_SymetriePuzzlePos[i]))
1013:                                 return FALSE;
1014:                 }
1015:         }
1016:         else
1017:         {
1018:                 m_SymetriePuzzlePos[0]=SUKPuzzlePos(0,                        0,                        0);
1019:                 m_SymetriePuzzlePos[1]=SUKPuzzlePos(0,                        m_nYSize-1,        m_nZSize-1);
1020:                 m_SymetriePuzzlePos[2]=SUKPuzzlePos(m_nXSize-1,        0,                        m_nZSize-1);
1021:                 m_SymetriePuzzlePos[3]=SUKPuzzlePos(m_nXSize-1,        m_nYSize-1,        0);
1022:         }
1023: 
1024:         for (int x=0;x<m_nXSize;x++)
1025:                 for (int y=0;y<m_nYSize;y++)
1026:                         for (int z=0;z<m_nZSize;z++)
1027:                         {
1028:                                 long nPosition=(x+m_nEdgeZone)*m_nDX+(y+m_nEdgeZone)*m_nDY+(z+m_nEdgeZone)*m_nDZ;
1029:                                 if (m_pBlock[nPosition]>=0)
1030:                                 {
1031:                                         m_pPositions[nPos]=nPosition;
1032:                                         arrPositionOrder[nPos]=m_pBlock[nPosition];
1033:                                         //just test if symetriepos[0] is the first pos

1034:                                         //if not then there is an error

1035: 
1036:                                         nPos++;
1037:                                         for (int i=0;i<m_nSymetriePosCount;i++)
1038:                                                 if (m_SymetriePuzzlePos[i].x==x && m_SymetriePuzzlePos[i].y==y && m_SymetriePuzzlePos[i].z==z)
1039:                                                         m_SymetriePos[i]=nPosition;        
1040: 
1041:                                         //m_pBlockPosToPosIndex[nPosition]=nPos-1;

1042:                                 }
1043:                         }
1044: 
1045:         m_nPositionCount=nPos;//Decrease the Position Count

1046: 
1047:         for (int i=1;i<m_nPositionCount;i++)
1048:                 for (int j=1;j<m_nPositionCount;j++)
1049:                         if (arrPositionOrder[j]<arrPositionOrder[j-1])
1050:                         {
1051:                                 long nTemp;
1052:                                 nTemp=m_pPositions[j];
1053:                                 m_pPositions[j]=m_pPositions[j-1];
1054:                                 m_pPositions[j-1]=nTemp;
1055:                                 nTemp=(long)arrPositionOrder[j];
1056:                                 arrPositionOrder[j]=arrPositionOrder[j-1];
1057:                                 arrPositionOrder[j-1]=(DWORD)nTemp;
1058:                         }
1059: 
1060:         if (m_nSymetriePosCount > 0 )
1061:         {
1062:                 long nPosition=(m_SymetriePuzzlePos[0].x+m_nEdgeZone)*m_nDX+(m_SymetriePuzzlePos[0].y+m_nEdgeZone)*m_nDY+(m_SymetriePuzzlePos[0].z+m_nEdgeZone)*m_nDZ;
1063:                 if (nPosition != m_pPositions[0])
1064:                         return FALSE;
1065:         }
1066: 
1067:         return TRUE;
1068: }
1069: 
1070: BOOL CUKPuzzleCore::PostInitBlock()
1071: {
1072:         ASSERT (m_nXSize>0 && m_nYSize>0 && m_nZSize>0 && m_nEdgeZone>0 && m_pBlock);
1073: 
1074:         for (int x=0;x<m_nXSize;x++)
1075:                 for (int y=0;y<m_nYSize;y++)
1076:                         for (int z=0;z<m_nZSize;z++)
1077:                         {
1078:                                 long nPosition=(x+m_nEdgeZone)*m_nDX+(y+m_nEdgeZone)*m_nDY+(z+m_nEdgeZone)*m_nDZ;
1079:                                 if (m_pBlock[nPosition] > 0)
1080:                                         m_pBlock[nPosition]=0;
1081:                         }
1082:         return TRUE;
1083: }
1084: 
1085: SUKPuzzlePos* __cdecl UKPP(SUKPuzzlePos* P,long nCount,...)
1086: {
1087:         va_list args;
1088:         va_start( args, nCount);
1089:         for (int i=0;i<nCount;i++)
1090:         {
1091:                 P[i].x=va_arg( args, long);
1092:                 P[i].y=va_arg( args, long);
1093:                 P[i].z=va_arg( args, long);
1094:         }
1095:         va_end( args);
1096:         return P;
1097: }
1098: 
1099: #define SET_STONE_I                m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 0,1,0, 0,2,0, 1,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1100: #define SET_STONE_II        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 1,1,0, 1,2,0, 2,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1101: #define SET_STONE_III   m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 1,1,0, 1,2,0, 1,3,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1102: #define SET_STONE_IV        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  0,1,0, 0,2,0, 0,3,0, 1,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1103: #define SET_STONE_V                m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 0,1,0, 0,0,1, 0,1,1),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1104: #define SET_STONE_VI        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 1,0,0,  1,1,0, 0,2,0, 1,2,0, 2,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1105: #define SET_STONE_VII        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 0,1,0, 1,1,0, 1,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1106: #define SET_STONE_VIII        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 0,0,0,  1,0,0, 1,1,0, 2,1,0, 2,2,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1107: #define SET_STONE_IX        m_ppStones[nQI][i][j++].SetStone(UKPP(P,4, 0,0,0,  1,0,0, 0,1,0, 0,1,1),4,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1108: #define SET_STONE_X                m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 1,0,0,  0,1,0, 0,2,0, 1,1,0, 2,1,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1109: #define SET_STONE_XI        m_ppStones[nQI][i][j++].SetStone(UKPP(P,5, 1,0,0,  0,1,0, 1,1,0, 1,2,0, 2,1,0),5,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);                
1110: #define SET_STONE_XII        m_ppStones[nQI][i][j++].SetStone(UKPP(P,6, 0,0,0,  1,0,0, 0,1,0, 0,2,0, 1,2,0, 0,3,0),6,m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1111: 
1112: BOOL CUKPuzzleCore::InitStones()
1113: {
1114:         CUKIniAccess theIniFile(m_strIniFileName);
1115: 
1116:         int i,j;
1117: 
1118:         ASSERT(m_nXSize>0 && m_nYSize>0 && m_nZSize>0);
1119:         ASSERT(m_nStoneCount>0);
1120:         
1121:         m_nEntireStoneCount=0;
1122: 
1123:         for (int nQI=0;nQI<enPreDefStones;nQI++)
1124:         {
1125:                 m_ppStones[nQI]=new CUKStone* [m_nXSize*m_nYSize*m_nZSize];
1126:                 if (!m_ppStones[nQI])
1127:                         return FALSE;
1128: 
1129:                 for (i=0;i<m_nXSize*m_nYSize*m_nZSize;i++)
1130:                         m_ppStones[nQI][i]=NULL;
1131: 
1132:                 for (i=0;i<m_nXSize*m_nYSize*m_nZSize;i++)
1133:                 {
1134:                         m_ppStones[nQI][i]=new CUKStone[m_nStoneCount];
1135: 
1136:                         if (!m_ppStones[nQI][i])
1137:                                 return FALSE;
1138:                 }
1139:         }
1140: 
1141:         m_pAvailableStones=new long[m_nStoneCount];
1142:         if (!m_pAvailableStones)
1143:                 return FALSE;
1144: 
1145:         SUKPuzzlePos P[enMaxCubesPerStone];
1146: 
1147:         CLongArray theStoneOrder;
1148:         if(m_bLoadFromIni)
1149:         {
1150:                 if (!theIniFile.ReadValue("StoneInfo","StoneOrder",theStoneOrder))
1151:                         return FALSE;
1152:                 if (theStoneOrder.GetSize()!=m_nStoneCount)
1153:                         return FALSE;
1154:                 for (i=0;i<m_nStoneCount;i++)
1155:                         if (theStoneOrder[i]<0 || theStoneOrder[i]>=m_nStoneCount)
1156:                                 return FALSE;
1157:                         else
1158:                                 for (j=i+1;j<m_nStoneCount;j++)
1159:                                         if (theStoneOrder[i]==theStoneOrder[j])
1160:                                                 return FALSE;
1161:         }
1162:         
1163:         for (i=0;i<m_nPositionCount;i++)
1164:         {
1165:                 nQI=0;
1166:                 long nPosition=m_pPositions[i];
1167:                 if (m_pBlock[nPosition]==0)
1168:                 {
1169:                         if(m_bLoadFromIni)
1170:                         {
1171:                                 m_nEntireStoneCount=0;
1172:                                 for (j=0;j<m_nStoneCount;j++)
1173:                                 {
1174:                                         CString strTmp;
1175:                                         strTmp.Format("Stone_%02d",theStoneOrder[j]);
1176: 
1177:                                         if (!ReadStone(theIniFile,"StoneInfo",strTmp,m_ppStones[nQI][i][j],m_pAvailableStones[j],m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock))
1178:                                                 return FALSE;
1179:                                         m_nEntireStoneCount+=m_pAvailableStones[j];
1180:                                 }
1181:                         }
1182:                         else
1183:                         {
1184:                                 //////////////////////////////////////////

1185:                                 //                (CornerPositions)        (Variations)

1186:                                 j=0;
1187:                                 SET_STONE_XI        // (0)                (6)

1188:                                 SET_STONE_VI        // (2/2)        (18)

1189:                                 SET_STONE_II        // (2/2)        (18)

1190:                                 SET_STONE_VIII        // (2/2)        (21)

1191:                                 SET_STONE_IV        // (2)                (36)

1192:                                 SET_STONE_X                // (1)                (42)

1193:                                 SET_STONE_IX        // (4)                (18) (3D)

1194:                                 SET_STONE_I                // (4/2)        (12)

1195:                                 SET_STONE_III        // (2)                (30)

1196:                                 SET_STONE_XII        // (3)                (30)

1197:                                 SET_STONE_V                // (5)                (33) (3D)

1198:                                 SET_STONE_VII        // (3)                (30)

1199:                                 //////////////////////////////////////////

1200:                         }
1201:                         for (j=0;j<m_nStoneCount;j++)
1202:                         {
1203:                                 for (nQI=1;nQI<enPreDefStones;nQI++)
1204:                                 {
1205:                                         if ((nQI&1)==1 && m_pBlock[nPosition+m_nDX]==0)
1206:                                                 m_pBlock[nPosition+m_nDX]=-3;
1207:                                         if ((nQI&2)==2 && m_pBlock[nPosition+m_nDY]==0)
1208:                                                 m_pBlock[nPosition+m_nDY]=-3;
1209:                                         if ((nQI&4)==4 && m_pBlock[nPosition+m_nDZ]==0)
1210:                                                 m_pBlock[nPosition+m_nDZ]=-3;
1211: 
1212:                                         if ((nQI&8)==8 && m_pBlock[nPosition-m_nDX]==0)
1213:                                                 m_pBlock[nPosition+m_nDX]=-3;
1214:                                         if ((nQI&16)==16 && m_pBlock[nPosition-m_nDY]==0)
1215:                                                 m_pBlock[nPosition+m_nDY]=-3;
1216:                                         if ((nQI&32)==32 && m_pBlock[nPosition-m_nDZ]==0)
1217:                                                 m_pBlock[nPosition+m_nDZ]=-3;
1218: 
1219:                                         m_ppStones[nQI][i][j].SetStone(m_ppStones[0][i][j],m_nDX,m_nDY,m_nDZ,nPosition,m_pBlock);
1220: 
1221:                                         if ((nQI&32)==32 && m_pBlock[nPosition-m_nDZ]==-3)
1222:                                                 m_pBlock[nPosition+m_nDZ]=0;
1223:                                         if ((nQI&16)==16 && m_pBlock[nPosition-m_nDY]==-3)
1224:                                                 m_pBlock[nPosition+m_nDY]=0;
1225:                                         if ((nQI&8)==8 && m_pBlock[nPosition-m_nDX]==-3)
1226:                                                 m_pBlock[nPosition+m_nDX]=0;
1227: 
1228:                                         if ((nQI&4)==4 && m_pBlock[nPosition+m_nDZ]==-3)
1229:                                                 m_pBlock[nPosition+m_nDZ]=0;
1230:                                         if ((nQI&2)==2 && m_pBlock[nPosition+m_nDY]==-3)
1231:                                                 m_pBlock[nPosition+m_nDY]=0;
1232:                                         if ((nQI&1)==1 && m_pBlock[nPosition+m_nDX]==-3)
1233:                                                 m_pBlock[nPosition+m_nDX]=0;                                        
1234:                                 }
1235:                         }
1236:                         m_pBlock[nPosition]=-2;
1237:                 }
1238:         }
1239: 
1240:         if (!m_bLoadFromIni)
1241:         {
1242:                 m_nEntireStoneCount=12;
1243:                 for (i=0;i<m_nStoneCount;i++)
1244:                         m_pAvailableStones[i]=1;
1245:         }
1246: 
1247:         for (i=0;i<m_nPositionCount;i++)
1248:         {
1249:                 long nPosition=m_pPositions[i];
1250:                 if (m_pBlock[nPosition]==-2)
1251:                         m_pBlock[nPosition]=0;
1252:         }
1253: 
1254:         m_pUsedStones=new SUKStoneDesc[m_nEntireStoneCount];
1255:         if (!m_pUsedStones)
1256:                 return FALSE;
1257: 
1258:         return TRUE;
1259: }
1260: 
1261: BOOL CUKPuzzleCore::Init(long nFirstStoneOnPos_0,long nLastStoneOnPos_0,LPCTSTR szIniFileName,LPCTSTR szOutputFileName)
1262: {                
1263:         m_nTrys=0;
1264: 
1265:         m_strOutputFileName=szOutputFileName;
1266: 
1267:         m_strIniFileName=szIniFileName;
1268:         if (m_strIniFileName!="")
1269:                 m_bLoadFromIni=TRUE;
1270: 
1271:         Deinit();
1272:         //Init vars

1273: 
1274:         CUKIniAccess theIniFile(m_strIniFileName);
1275:         BOOL bIniOK=TRUE;
1276:         
1277:         if (m_bLoadFromIni)
1278:         {
1279:                 bIniOK = bIniOK && theIniFile.ReadValue("BlockInfo","XSize",&m_nXSize);
1280:                 bIniOK = bIniOK && theIniFile.ReadValue("BlockInfo","YSize",&m_nYSize);
1281:                 bIniOK = bIniOK && theIniFile.ReadValue("BlockInfo","ZSize",&m_nZSize);
1282:                 bIniOK = bIniOK && theIniFile.ReadValue("BlockInfo","EdgeZone",&m_nEdgeZone);
1283: 
1284:                 bIniOK = bIniOK && theIniFile.ReadValue("StoneInfo","StoneCount",&m_nStoneCount);
1285: 
1286:                 bIniOK = bIniOK && theIniFile.ReadValue("SymetryInfo","EnhancedSymetryCheck",&m_bEnhancedSymertyCheck);
1287:                 bIniOK = bIniOK && theIniFile.ReadValue("SymetryInfo","SymetryPosCount",&m_nSymetriePosCount);
1288: 
1289:                 if (m_strOutputFileName=="" || !theIniFile.ReadValue("OutputInfo","WriteEveryNSolution",&m_nWriteEveryNSolution))
1290:                         m_nWriteEveryNSolution=0;
1291: 
1292:                 m_bShowLegend=theIniFile.ReadValueDef("StoneInfo","ShowLegend",1L);
1293: 
1294:                 m_nPreCheckLevel=theIniFile.ReadValueDef("StoneInfo","PreCheckLevel",(int)0);
1295:                 m_nFirstPreCheckStone=theIniFile.ReadValueDef("StoneInfo","FirstPreCheckStone",1);
1296:                 m_nLastPreCheckStone=theIniFile.ReadValueDef("StoneInfo","LastPreCheckStone",m_nStoneCount-2);
1297:         }
1298: 
1299:         if (!bIniOK || !m_bLoadFromIni)
1300:         {
1301:                 //Use the Default Parameter

1302:                 m_nXSize=5,
1303:                 m_nYSize=4,
1304:                 m_nZSize=3,
1305:                 m_nEdgeZone=3,
1306:                 m_nStoneCount=12;
1307:                 m_nSymetriePosCount=4;
1308:                 m_bEnhancedSymertyCheck=FALSE;
1309: 
1310:                 m_nWriteEveryNSolution=0;
1311:                 m_bShowLegend=0;
1312: 
1313:                 m_bLoadFromIni=FALSE;
1314: 
1315:                 m_nPreCheckLevel=2;
1316:                 m_nFirstPreCheckStone=3;
1317:                 m_nLastPreCheckStone=10;
1318:         }
1319: 
1320:         m_nDX=1;
1321:         m_nDY=1*(m_nXSize+2*m_nEdgeZone);
1322:         m_nDZ=1*(m_nXSize+2*m_nEdgeZone)*(m_nYSize+2*m_nEdgeZone);
1323:         m_nPositionCount=m_nXSize*m_nYSize*m_nZSize;
1324: 
1325:         ///////////////////////////////////////////////////////////////

1326:         if (nFirstStoneOnPos_0>=0 && nFirstStoneOnPos_0<m_nStoneCount)
1327:                 m_nFirstStoneOnPos_0=nFirstStoneOnPos_0;
1328:         else
1329:                 m_nFirstStoneOnPos_0=0;
1330:         ///////////////////////////////////////////////////////////////

1331:         if (nLastStoneOnPos_0>=0 && nLastStoneOnPos_0<m_nStoneCount)
1332:                 m_nLastStoneOnPos_0=min(nLastStoneOnPos_0,m_nStoneCount-m_nSymetriePosCount);
1333:         else
1334:                 m_nLastStoneOnPos_0=m_nStoneCount-m_nSymetriePosCount;
1335:         ///////////////////////////////////////////////////////////////

1336: 
1337:         if (m_nXSize<=0 || m_nYSize<=0 || m_nZSize<=0 || m_nEdgeZone<=0)
1338:                 return FALSE;
1339: 
1340:         if (m_nDX<=0 || m_nDY<=0 || m_nDZ<=0)
1341:                 return FALSE;
1342: 
1343:         if (m_nPositionCount<=0 || m_nStoneCount<=0)
1344:                 return FALSE;
1345: 
1346:         if (m_nSymetriePosCount<0 || m_nSymetriePosCount>=8)
1347:                 return FALSE;
1348: 
1349:         //////////////////////////////////////////////////////////

1350: 
1351:         //////////////////////////////////////////

1352: #ifdef UKPUZ_WRITEOUTPUT
1353:         //////////////////////////////////////////

1354:         if (m_nWriteEveryNSolution >0)
1355:         {
1356:                 CStdioFile theFile(m_strOutputFileName,CFile::modeCreate);
1357:                 theFile.Close();
1358:         }
1359:         //////////////////////////////////////////

1360: #endif

1361:         //////////////////////////////////////////

1362: 
1363:         m_nUsedStoneCount=0;
1364:         m_nNextFreeStone=0;
1365:         m_nSolutionsFound=0;
1366:         m_nNextFreePosIndex=0;
1367: 
1368:         BOOL bOK=TRUE;
1369: 
1370:         if ((m_nFirstStoneOnPos_0 > m_nStoneCount-m_nSymetriePosCount) ||
1371:                 (m_nFirstStoneOnPos_0 > m_nLastStoneOnPos_0))
1372:         {
1373:                 //No more initialization needed at this time

1374:                 m_bHasFinished=TRUE;
1375:                 m_nNextStep=enFinished;
1376:         }
1377:         else
1378:         {
1379:                 m_bHasFinished=FALSE;
1380:                 m_nNextStep=enNextStone;
1381: 
1382:                 bOK = bOK && PreInitBlock();
1383:                 bOK = bOK && InitPositionOrder();
1384:                 bOK = bOK && PostInitBlock();
1385:                 bOK = bOK && InitStones();
1386:         }
1387: 
1388:         m_nSymetryStones=m_nEntireStoneCount;
1389:         m_nSymetryStonesNeeded=m_nSymetriePosCount-1;
1390: 
1391:         if (!bOK)
1392:         {
1393:                 Deinit();
1394:                 return FALSE;
1395:         }
1396: 
1397:         m_bIsInit=TRUE;
1398:         return TRUE;
1399: }
1400: 
1401: void CUKPuzzleCore::DeinitStones()
1402: {
1403:         for (int nQI=0;nQI<enPreDefStones;nQI++)
1404:         {
1405:                 if (m_ppStones[nQI])
1406:                 {
1407:                         for (int i=0;i<m_nXSize*m_nYSize*m_nZSize;i++)
1408:                         {
1409:                                 if (m_ppStones[nQI][i])
1410:                                         delete[] m_ppStones[nQI][i];
1411:                                 m_ppStones[nQI][i]=NULL;
1412:                         }
1413:                         delete[] m_ppStones[nQI];
1414:                 }
1415:                 m_ppStones[nQI]=NULL;
1416:         }
1417:         if (m_pAvailableStones)
1418:                 delete[] m_pAvailableStones;
1419:         m_pAvailableStones=NULL;
1420: 
1421:         if (m_pUsedStones)
1422:                 delete[] m_pUsedStones;
1423:         m_pUsedStones=NULL;
1424: }
1425: 
1426: void CUKPuzzleCore::DeinitPositionOrder()
1427: {
1428:         if (m_pPositions)
1429:                 delete[] m_pPositions;
1430:         m_pPositions=NULL;
1431: }
1432: 
1433: void CUKPuzzleCore::DeinitBlock()
1434: {
1435:         if (m_pBlock)
1436:                 delete m_pBlock;
1437:         m_pBlock=NULL;
1438:         //if (m_pBlockPosToPosIndex)

1439:         //        delete m_pBlockPosToPosIndex;

1440:         //m_pBlockPosToPosIndex=NULL;

1441: 
1442: }
1443: 
1444: void CUKPuzzleCore::Deinit()
1445: {
1446:         DeinitStones();
1447:         DeinitPositionOrder();
1448:         DeinitBlock();
1449:         
1450:         m_bIsInit=FALSE;
1451: }
1452: //(De)Init Functions end

1453: //////////////////////////////////////////////////////////