0001:
0002:
0003:
0004:
0005:
0006:
0007:
0008:
0009:
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:
0023:
0024:
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:
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:
0046:
0047:
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:
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:
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:
0196: switch ((i/m_nCubeCount)%4)
0197: {
0198: case 3:theCube.RotateX();
0199: case 2:theCube.RotateX();
0200: case 1:theCube.RotateX();
0201: case 0:;
0202: }
0203:
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:
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:
0220: long nInsertPosition=nPosition+theCube.x*nDX+theCube.y*nDY+theCube.z*nDZ;
0221: if (IsInvalid(nInsertPosition,pBlock))
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:
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:
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))
0306: m_pCubes[i][j]=enInvalid;
0307: else
0308: m_pCubes[i][j]=rStone.m_pCubes[i][j];
0309: }
0310: }
0311:
0312: EliminateInvalidStones();
0313:
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)
0340: {
0341:
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:
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:
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:
0460: void CUKPuzzleCore::WriteOutput(LPCTSTR szFileName)
0461: {
0462:
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;
0486: for (int yPos=m_nYSize+m_nEdgeZone-1;yPos>=m_nEdgeZone;yPos--)
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:
0521:
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()
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:
0623: switch (m_nPreCheckLevel)
0624: {
0625: case 1:
0626:
0627: return PreCheck1();
0628:
0629: case 2:
0630:
0631: return PreCheck1();
0632:
0633: default:
0634: return TRUE;
0635:
0636: }
0637:
0638:
0639:
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:
0733:
0734:
0735:
0736:
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:
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];
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:
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:
0948:
0949:
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;
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;
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:
1034:
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:
1042: }
1043: }
1044:
1045: m_nPositionCount=nPos;
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:
1186: j=0;
1187: SET_STONE_XI
1188: SET_STONE_VI
1189: SET_STONE_II
1190: SET_STONE_VIII
1191: SET_STONE_IV
1192: SET_STONE_X
1193: SET_STONE_IX
1194: SET_STONE_I
1195: SET_STONE_III
1196: SET_STONE_XII
1197: SET_STONE_V
1198: SET_STONE_VII
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:
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:
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:
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:
1439:
1440:
1441:
1442: }
1443:
1444: void CUKPuzzleCore::Deinit()
1445: {
1446: DeinitStones();
1447: DeinitPositionOrder();
1448: DeinitBlock();
1449:
1450: m_bIsInit=FALSE;
1451: }
1452:
1453: