perfect: Format code with msvc

This commit is contained in:
Calcitem 2021-01-20 01:38:08 +08:00
parent 5c71717a9c
commit f74762d2c7
29 changed files with 7717 additions and 8545 deletions

View File

@ -27,8 +27,7 @@ BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSize
bytesInReadBuffer = new unsigned int[numThreads]; bytesInReadBuffer = new unsigned int[numThreads];
bytesInWriteBuffer = new unsigned int[numThreads]; bytesInWriteBuffer = new unsigned int[numThreads];
for (curThread = 0; curThread < numThreads; curThread++) for (curThread = 0; curThread < numThreads; curThread++) {
{
curReadingPointer[curThread] = 0; curReadingPointer[curThread] = 0;
curWritingPointer[curThread] = 0; curWritingPointer[curThread] = 0;
bytesInReadBuffer[curThread] = 0; bytesInReadBuffer[curThread] = 0;
@ -40,8 +39,7 @@ BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSize
hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE) {
{
hFile = nullptr; hFile = nullptr;
return; return;
} }
@ -91,8 +89,7 @@ long long BufferedFile::getFileSize()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool BufferedFile::flushBuffers() bool BufferedFile::flushBuffers()
{ {
for (unsigned int threadNo = 0; threadNo < numThreads; threadNo++) for (unsigned int threadNo = 0; threadNo < numThreads; threadNo++) {
{
writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]);
bytesInWriteBuffer[threadNo] = 0; bytesInWriteBuffer[threadNo] = 0;
} }
@ -115,18 +112,14 @@ void BufferedFile::writeDataToFile(HANDLE hFile, long long offset, unsigned int
while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN))
cout << endl cout << endl
<< "SetFilePointerEx failed!"; << "SetFilePointerEx failed!";
while (restingBytes > 0) while (restingBytes > 0) {
{ if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) {
if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE)
{
restingBytes -= dwBytesWritten; restingBytes -= dwBytesWritten;
pData = (void *)(((unsigned char *)pData) + dwBytesWritten); pData = (void *)(((unsigned char *)pData) + dwBytesWritten);
if (restingBytes > 0) if (restingBytes > 0)
cout << endl cout << endl
<< "Still " << restingBytes << " to write!"; << "Still " << restingBytes << " to write!";
} } else {
else
{
cout << endl cout << endl
<< "WriteFile Failed!"; << "WriteFile Failed!";
} }
@ -150,18 +143,14 @@ void BufferedFile::readDataFromFile(HANDLE hFile, long long offset, unsigned int
while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN))
cout << endl cout << endl
<< "SetFilePointerEx failed!"; << "SetFilePointerEx failed!";
while (restingBytes > 0) while (restingBytes > 0) {
{ if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) {
if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE)
{
restingBytes -= dwBytesRead; restingBytes -= dwBytesRead;
pData = (void *)(((unsigned char *)pData) + dwBytesRead); pData = (void *)(((unsigned char *)pData) + dwBytesRead);
if (restingBytes > 0) if (restingBytes > 0)
cout << endl cout << endl
<< "Still " << restingBytes << " to read!"; << "Still " << restingBytes << " to read!";
} } else {
else
{
cout << endl cout << endl
<< "ReadFile Failed!"; << "ReadFile Failed!";
} }
@ -193,8 +182,7 @@ bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, u
// locals // locals
// if buffer full or not sequential write operation write buffer to file // if buffer full or not sequential write operation write buffer to file
if (bytesInWriteBuffer[threadNo] && (positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) if (bytesInWriteBuffer[threadNo] && (positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) {
{
writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]);
bytesInWriteBuffer[threadNo] = 0; bytesInWriteBuffer[threadNo] = 0;
@ -231,8 +219,7 @@ bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, un
return false; return false;
// read from file into buffer if not enough data in buffer or if it is not an sequential reading operation? // read from file into buffer if not enough data in buffer or if it is not an sequential reading operation?
if (positionInFile != curReadingPointer[threadNo] || bytesInReadBuffer[threadNo] < numBytes) if (positionInFile != curReadingPointer[threadNo] || bytesInReadBuffer[threadNo] < numBytes) {
{
bytesInReadBuffer[threadNo] = ((positionInFile + bufferSize <= fileSize) ? bufferSize : (unsigned int)(fileSize - positionInFile)); bytesInReadBuffer[threadNo] = ((positionInFile + bufferSize <= fileSize) ? bufferSize : (unsigned int)(fileSize - positionInFile));
if (bytesInReadBuffer[threadNo] < numBytes) if (bytesInReadBuffer[threadNo] < numBytes)
return false; return false;

View File

@ -29,8 +29,7 @@ CyclicArray::CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlo
hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE) {
{
hFile = nullptr; hFile = nullptr;
return; return;
} }
@ -67,18 +66,14 @@ void CyclicArray::writeDataToFile(HANDLE hFile, long long offset, unsigned int s
cout << endl cout << endl
<< "SetFilePointerEx failed!"; << "SetFilePointerEx failed!";
while (restingBytes > 0) while (restingBytes > 0) {
{ if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) {
if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE)
{
restingBytes -= dwBytesWritten; restingBytes -= dwBytesWritten;
pData = (void *)(((unsigned char *)pData) + dwBytesWritten); pData = (void *)(((unsigned char *)pData) + dwBytesWritten);
if (restingBytes > 0) if (restingBytes > 0)
cout << endl cout << endl
<< "Still " << restingBytes << " to write!"; << "Still " << restingBytes << " to write!";
} } else {
else
{
cout << endl cout << endl
<< "WriteFile Failed!"; << "WriteFile Failed!";
} }
@ -101,18 +96,14 @@ void CyclicArray::readDataFromFile(HANDLE hFile, long long offset, unsigned int
cout << endl cout << endl
<< "SetFilePointerEx failed!"; << "SetFilePointerEx failed!";
while (restingBytes > 0) while (restingBytes > 0) {
{ if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) {
if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE)
{
restingBytes -= dwBytesRead; restingBytes -= dwBytesRead;
pData = (void *)(((unsigned char *)pData) + dwBytesRead); pData = (void *)(((unsigned char *)pData) + dwBytesRead);
if (restingBytes > 0) if (restingBytes > 0)
cout << endl cout << endl
<< "Still " << restingBytes << " to read!"; << "Still " << restingBytes << " to read!";
} } else {
else
{
cout << endl cout << endl
<< "ReadFile Failed!"; << "ReadFile Failed!";
} }
@ -130,8 +121,7 @@ bool CyclicArray::addBytes(unsigned int numBytes, unsigned char *pData)
unsigned int bytesWritten = 0; unsigned int bytesWritten = 0;
// write each byte // write each byte
while (bytesWritten < numBytes) while (bytesWritten < numBytes) {
{
// store byte in current reading block // store byte in current reading block
*curWritingPointer = *pData; *curWritingPointer = *pData;
@ -140,12 +130,10 @@ bool CyclicArray::addBytes(unsigned int numBytes, unsigned char *pData)
pData++; pData++;
// when block is full then save current one to file and begin new one // when block is full then save current one to file and begin new one
if (curWritingPointer == writingBlock + blockSize) if (curWritingPointer == writingBlock + blockSize) {
{
// copy data into reading block? // copy data into reading block?
if (curReadingBlock == curWritingBlock) if (curReadingBlock == curWritingBlock) {
{
memcpy(readingBlock, writingBlock, blockSize); memcpy(readingBlock, writingBlock, blockSize);
curReadingPointer = readingBlock + (curReadingPointer - writingBlock); curReadingPointer = readingBlock + (curReadingPointer - writingBlock);
} }
@ -192,8 +180,7 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData)
unsigned int bytesRead = 0; unsigned int bytesRead = 0;
// read each byte // read each byte
while (bytesRead < numBytes) while (bytesRead < numBytes) {
{
// was current reading byte already written ? // was current reading byte already written ?
if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound) if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound)
@ -206,8 +193,7 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData)
pData++; pData++;
// load next block? // load next block?
if (curReadingPointer == readingBlock + blockSize) if (curReadingPointer == readingBlock + blockSize) {
{
// go to next block // go to next block
curReadingBlock = (curReadingBlock + 1) % numBlocks; curReadingBlock = (curReadingBlock + 1) % numBlocks;
@ -215,12 +201,9 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData)
readWriteInSameRound = true; readWriteInSameRound = true;
// writing block reached ? // writing block reached ?
if (curReadingBlock == curWritingBlock) if (curReadingBlock == curWritingBlock) {
{
curReadingPointer = writingBlock; curReadingPointer = writingBlock;
} } else {
else
{
// set pointer to beginnig of reading block // set pointer to beginnig of reading block
curReadingPointer = readingBlock; curReadingPointer = readingBlock;
@ -261,16 +244,14 @@ bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded)
hLoadFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); hLoadFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hLoadFile == INVALID_HANDLE_VALUE) if (hLoadFile == INVALID_HANDLE_VALUE) {
{
return false; return false;
} }
// does data of file fit into cyclic array ? // does data of file fit into cyclic array ?
GetFileSizeEx(hLoadFile, &largeInt); GetFileSizeEx(hLoadFile, &largeInt);
if (maxFileSize < largeInt.QuadPart) if (maxFileSize < largeInt.QuadPart) {
{
CloseHandle(hLoadFile); CloseHandle(hLoadFile);
return false; return false;
} }
@ -287,8 +268,7 @@ bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded)
dataInFile = new unsigned char[blockSize]; dataInFile = new unsigned char[blockSize];
// //
for (curBlock = 0; curBlock < numBlocksInFile - 1; curBlock++, curOffset += blockSize) for (curBlock = 0; curBlock < numBlocksInFile - 1; curBlock++, curOffset += blockSize) {
{
// load data from file // load data from file
readDataFromFile(hLoadFile, curOffset, blockSize, dataInFile); readDataFromFile(hLoadFile, curOffset, blockSize, dataInFile);
@ -325,8 +305,7 @@ bool CyclicArray::saveFile(const char *fileName)
void *pointer; void *pointer;
// cyclic array file must be open // cyclic array file must be open
if (hFile == nullptr) if (hFile == nullptr) {
{
return false; return false;
} }
@ -334,8 +313,7 @@ bool CyclicArray::saveFile(const char *fileName)
hSaveFile = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hSaveFile = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hSaveFile == INVALID_HANDLE_VALUE) if (hSaveFile == INVALID_HANDLE_VALUE) {
{
return false; return false;
} }
@ -344,27 +322,19 @@ bool CyclicArray::saveFile(const char *fileName)
curBlock = curReadingBlock; curBlock = curReadingBlock;
dataInFile = new unsigned char[blockSize]; dataInFile = new unsigned char[blockSize];
do do {
{
// copy current block // copy current block
if (curBlock == curWritingBlock && curBlock == curReadingBlock) if (curBlock == curWritingBlock && curBlock == curReadingBlock) {
{
pointer = curReadingPointer; pointer = curReadingPointer;
bytesToWrite = (unsigned int)(curWritingPointer - curReadingPointer); bytesToWrite = (unsigned int)(curWritingPointer - curReadingPointer);
} } else if (curBlock == curWritingBlock) {
else if (curBlock == curWritingBlock)
{
pointer = writingBlock; pointer = writingBlock;
bytesToWrite = (unsigned int)(curWritingPointer - writingBlock); bytesToWrite = (unsigned int)(curWritingPointer - writingBlock);
} } else if (curBlock == curReadingBlock) {
else if (curBlock == curReadingBlock)
{
pointer = curReadingPointer; pointer = curReadingPointer;
bytesToWrite = blockSize - (unsigned int)(curReadingPointer - readingBlock); bytesToWrite = blockSize - (unsigned int)(curReadingPointer - readingBlock);
} } else {
else
{
readDataFromFile(hFile, ((long long)curBlock) * ((long long)blockSize), blockSize, dataInFile); readDataFromFile(hFile, ((long long)curBlock) * ((long long)blockSize), blockSize, dataInFile);
pointer = dataInFile; pointer = dataInFile;
bytesToWrite = blockSize; bytesToWrite = blockSize;

View File

@ -47,8 +47,7 @@ int main(void)
pos->beginNewGame(ai, ai, (rand() % 2) ? fieldStruct::playerOne : fieldStruct::playerTwo); pos->beginNewGame(ai, ai, (rand() % 2) ? fieldStruct::playerOne : fieldStruct::playerTwo);
#endif // SELF_PLAY #endif // SELF_PLAY
if (calculateDatabase) if (calculateDatabase) {
{
// calculate // calculate
ai->calculateDatabase(MAX_DEPTH_OF_TREE, false); ai->calculateDatabase(MAX_DEPTH_OF_TREE, false);
@ -61,9 +60,7 @@ int main(void)
<< "End test at layer: "; << "End test at layer: ";
endTestAtLayer; endTestAtLayer;
ai->testLayers(startTestFromLayer, endTestAtLayer); ai->testLayers(startTestFromLayer, endTestAtLayer);
} } else {
else
{
#ifdef SELF_PLAY #ifdef SELF_PLAY
int moveCount = 0; int moveCount = 0;
@ -79,8 +76,7 @@ int main(void)
#endif // SELF_PLAY #endif // SELF_PLAY
// play // play
do do {
{
// print board // print board
cout << "\n\n\n\n\n\n\n\n\n\n\n"; cout << "\n\n\n\n\n\n\n\n\n\n\n";
pos->getComputersChoice(&pushFrom, &pushTo); pos->getComputersChoice(&pushFrom, &pushTo);
@ -89,8 +85,7 @@ int main(void)
#ifdef SELF_PLAY #ifdef SELF_PLAY
moveCount++; moveCount++;
if (moveCount > 99) if (moveCount > 99) {
{
goto out; goto out;
} }
#endif // SELF_PLAY #endif // SELF_PLAY
@ -98,10 +93,8 @@ int main(void)
pos->printBoard(); pos->printBoard();
// Human // Human
if ((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman)) if ((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman)) {
{ do {
do
{
// Show text // Show text
if (pos->mustStoneBeRemoved()) if (pos->mustStoneBeRemoved())
cout << "\n Which stone do you want to remove? [a-x]: \n\n\n"; cout << "\n Which stone do you want to remove? [a-x]: \n\n\n";
@ -117,15 +110,12 @@ int main(void)
else else
pushFrom = fieldStruct::size; pushFrom = fieldStruct::size;
if (pos->inSettingPhase()) if (pos->inSettingPhase()) {
{
if ((ch[0] >= 'a') && (ch[0] <= 'x')) if ((ch[0] >= 'a') && (ch[0] <= 'x'))
pushTo = ch[0] - 'a'; pushTo = ch[0] - 'a';
else else
pushTo = fieldStruct::size; pushTo = fieldStruct::size;
} } else {
else
{
if ((ch[1] >= 'a') && (ch[1] <= 'x')) if ((ch[1] >= 'a') && (ch[1] <= 'x'))
pushTo = ch[1] - 'a'; pushTo = ch[1] - 'a';
else else
@ -133,12 +123,10 @@ int main(void)
} }
// undo // undo
if (ch[0] == 'u' && ch[1] == 'n' && ch[2] == 'd' && ch[3] == 'o') if (ch[0] == 'u' && ch[1] == 'n' && ch[2] == 'd' && ch[3] == 'o') {
{
// undo moves until a human player shall move // undo moves until a human player shall move
do do {
{
pos->undo_move(); pos->undo_move();
} while (!((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman))); } while (!((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman)));
@ -149,9 +137,7 @@ int main(void)
} while (pos->do_move(pushFrom, pushTo) == false); } while (pos->do_move(pushFrom, pushTo) == false);
// Computer // Computer
} } else {
else
{
cout << "\n"; cout << "\n";
pos->do_move(pushFrom, pushTo); pos->do_move(pushFrom, pushTo);
} }

View File

@ -60,8 +60,7 @@ void fieldStruct::printBoard()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
char fieldStruct::GetCharFromStone(int stone) char fieldStruct::GetCharFromStone(int stone)
{ {
switch (stone) switch (stone) {
{
case fieldStruct::playerOne: case fieldStruct::playerOne:
return 'o'; return 'o';
case fieldStruct::playerTwo: case fieldStruct::playerTwo:
@ -93,15 +92,13 @@ void fieldStruct::copyBoard(fieldStruct *destination)
destination->settingPhase = this->settingPhase; destination->settingPhase = this->settingPhase;
destination->stoneMustBeRemoved = this->stoneMustBeRemoved; destination->stoneMustBeRemoved = this->stoneMustBeRemoved;
for (i = 0; i < this->size; i++) for (i = 0; i < this->size; i++) {
{
destination->board[i] = this->board[i]; destination->board[i] = this->board[i];
destination->warnings[i] = this->warnings[i]; destination->warnings[i] = this->warnings[i];
destination->stonePartOfMill[i] = this->stonePartOfMill[i]; destination->stonePartOfMill[i] = this->stonePartOfMill[i];
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++) {
{
destination->connectedSquare[i][j] = this->connectedSquare[i][j]; destination->connectedSquare[i][j] = this->connectedSquare[i][j];
destination->stoneMoveAble[i][j] = this->stoneMoveAble[i][j]; destination->stoneMoveAble[i][j] = this->stoneMoveAble[i][j];
@ -157,8 +154,7 @@ void fieldStruct::createBoard()
oppPlayer->numStonesMissing = 0; oppPlayer->numStonesMissing = 0;
// zero // zero
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
{
board[i] = squareIsFree; board[i] = squareIsFree;
warnings[i] = noWarning; warnings[i] = noWarning;
stonePartOfMill[i] = 0; stonePartOfMill[i] = 0;

View File

@ -39,8 +39,7 @@ void MiniMaxAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
unsigned int searchDepth; unsigned int searchDepth;
// automatic depth // automatic depth
if (depthOfFullTree == 0) if (depthOfFullTree == 0) {
{
if (theField->settingPhase) if (theField->settingPhase)
searchDepth = 5; searchDepth = 5;
else if (theField->curPlayer->numStones <= 4) else if (theField->curPlayer->numStones <= 4)
@ -49,9 +48,7 @@ void MiniMaxAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
searchDepth = 7; searchDepth = 7;
else else
searchDepth = 7; searchDepth = 7;
} } else {
else
{
searchDepth = depthOfFullTree; searchDepth = depthOfFullTree;
} }
@ -67,18 +64,13 @@ void MiniMaxAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
Possibility *rootPossibilities = (Possibility *)getBestChoice(searchDepth, &bestChoice, MAX_NUM_POS_MOVES); Possibility *rootPossibilities = (Possibility *)getBestChoice(searchDepth, &bestChoice, MAX_NUM_POS_MOVES);
// decode the best choice // decode the best choice
if (field->stoneMustBeRemoved) if (field->stoneMustBeRemoved) {
{
*pushFrom = bestChoice; *pushFrom = bestChoice;
*pushTo = 0; *pushTo = 0;
} } else if (field->settingPhase) {
else if (field->settingPhase)
{
*pushFrom = 0; *pushFrom = 0;
*pushTo = bestChoice; *pushTo = bestChoice;
} } else {
else
{
*pushFrom = rootPossibilities->from[bestChoice]; *pushFrom = rootPossibilities->from[bestChoice];
*pushTo = rootPossibilities->to[bestChoice]; *pushTo = rootPossibilities->to[bestChoice];
} }
@ -123,12 +115,10 @@ unsigned int *MiniMaxAI::getPossSettingPhase(unsigned int *numPossibilities, voi
unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES];
// possibilities with cut off // possibilities with cut off
for ((*numPossibilities) = 0, i = 0; i < field->size; i++) for ((*numPossibilities) = 0, i = 0; i < field->size; i++) {
{
// move possible ? // move possible ?
if (field->board[i] == field->squareIsFree) if (field->board[i] == field->squareIsFree) {
{
idPossibility[*numPossibilities] = i; idPossibility[*numPossibilities] = i;
(*numPossibilities)++; (*numPossibilities)++;
@ -153,20 +143,16 @@ unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void
Possibility *possibility = &possibilities[curSearchDepth]; Possibility *possibility = &possibilities[curSearchDepth];
// if he is not allowed to spring // if he is not allowed to spring
if (field->curPlayer->numStones > 3) if (field->curPlayer->numStones > 3) {
{
for ((*numPossibilities) = 0, from = 0; from < field->size; from++) for ((*numPossibilities) = 0, from = 0; from < field->size; from++) {
{ for (dir = 0; dir < 4; dir++) {
for (dir = 0; dir < 4; dir++)
{
// destination // destination
to = field->connectedSquare[from][dir]; to = field->connectedSquare[from][dir];
// move possible ? // move possible ?
if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) {
{
// stone is moveable // stone is moveable
idPossibility[*numPossibilities] = *numPossibilities; idPossibility[*numPossibilities] = *numPossibilities;
@ -178,18 +164,13 @@ unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void
} }
} }
} }
} } else {
else
{
for ((*numPossibilities) = 0, from = 0; from < field->size; from++) for ((*numPossibilities) = 0, from = 0; from < field->size; from++) {
{ for (to = 0; to < field->size; to++) {
for (to = 0; to < field->size; to++)
{
// move possible ? // move possible ?
if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) {
{
// stone is moveable // stone is moveable
idPossibility[*numPossibilities] = *numPossibilities; idPossibility[*numPossibilities] = *numPossibilities;
@ -218,12 +199,10 @@ unsigned int *MiniMaxAI::getPossStoneRemove(unsigned int *numPossibilities, void
unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES];
// possibilities with cut off // possibilities with cut off
for ((*numPossibilities) = 0, i = 0; i < field->size; i++) for ((*numPossibilities) = 0, i = 0; i < field->size; i++) {
{
// move possible ? // move possible ?
if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) {
{
idPossibility[*numPossibilities] = i; idPossibility[*numPossibilities] = i;
(*numPossibilities)++; (*numPossibilities)++;
@ -246,14 +225,11 @@ unsigned int *MiniMaxAI::getPossibilities(unsigned int threadNo, unsigned int *n
*opponentsMove = (field->curPlayer->id == ownId) ? false : true; *opponentsMove = (field->curPlayer->id == ownId) ? false : true;
// When game has ended of course nothing happens any more // When game has ended of course nothing happens any more
if (gameHasFinished) if (gameHasFinished) {
{
*numPossibilities = 0; *numPossibilities = 0;
return 0; return 0;
// look what is to do // look what is to do
} } else {
else
{
if (field->stoneMustBeRemoved) if (field->stoneMustBeRemoved)
return getPossStoneRemove(numPossibilities, pPossibilities); return getPossStoneRemove(numPossibilities, pPossibilities);
else if (field->settingPhase) else if (field->settingPhase)
@ -310,8 +286,7 @@ void MiniMaxAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opp
field->board[oldState->to] = oldState->fieldTo; field->board[oldState->to] = oldState->fieldTo;
// very expensive // very expensive
for (int i = 0; i < field->size; i++) for (int i = 0; i < field->size; i++) {
{
field->stonePartOfMill[i] = oldState->stonePartOfMill[i]; field->stonePartOfMill[i] = oldState->stonePartOfMill[i];
field->warnings[i] = oldState->warnings[i]; field->warnings[i] = oldState->warnings[i];
} }
@ -324,8 +299,7 @@ void MiniMaxAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opp
inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree) inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree)
{ {
// if all 3 fields are occupied by current player than he closed a mill // if all 3 fields are occupied by current player than he closed a mill
if (field->board[stoneOne] == field->curPlayer->id && field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) if (field->board[stoneOne] == field->curPlayer->id && field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) {
{
field->stonePartOfMill[stoneOne]++; field->stonePartOfMill[stoneOne]++;
field->stonePartOfMill[stoneTwo]++; field->stonePartOfMill[stoneTwo]++;
@ -334,8 +308,7 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo,
} }
// is a mill destroyed ? // is a mill destroyed ?
if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) {
{
field->stonePartOfMill[stoneOne]--; field->stonePartOfMill[stoneOne]--;
field->stonePartOfMill[stoneTwo]--; field->stonePartOfMill[stoneTwo]--;
@ -343,8 +316,7 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo,
} }
// stone was set // stone was set
if (field->board[stoneOne] == field->curPlayer->id) if (field->board[stoneOne] == field->curPlayer->id) {
{
// a warnig was destroyed // a warnig was destroyed
field->warnings[stoneOne] = field->noWarning; field->warnings[stoneOne] = field->noWarning;
@ -356,9 +328,7 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo,
field->warnings[stoneTwo] |= field->curPlayer->warning; field->warnings[stoneTwo] |= field->curPlayer->warning;
// stone was removed // stone was removed
} } else if (field->board[stoneOne] == field->squareIsFree) {
else if (field->board[stoneOne] == field->squareIsFree)
{
// a warning is created // a warning is created
if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id)
@ -367,8 +337,7 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo,
field->warnings[stoneOne] |= field->oppPlayer->warning; field->warnings[stoneOne] |= field->oppPlayer->warning;
// a warning is destroyed // a warning is destroyed
if (field->warnings[stoneTwo] && field->board[stoneThree] != field->squareIsFree) if (field->warnings[stoneTwo] && field->board[stoneThree] != field->squareIsFree) {
{
// reset warning if necessary // reset warning if necessary
if (field->board[field->neighbour[stoneTwo][0][0]] == field->curPlayer->id && field->board[field->neighbour[stoneTwo][0][1]] == field->curPlayer->id) if (field->board[field->neighbour[stoneTwo][0][0]] == field->curPlayer->id && field->board[field->neighbour[stoneTwo][0][1]] == field->curPlayer->id)
@ -381,9 +350,7 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo,
field->warnings[stoneTwo] = field->oppPlayer->warning; field->warnings[stoneTwo] = field->oppPlayer->warning;
else else
field->warnings[stoneTwo] = field->noWarning; field->warnings[stoneTwo] = field->noWarning;
} } else if (field->warnings[stoneThree] && field->board[stoneTwo] != field->squareIsFree) {
else if (field->warnings[stoneThree] && field->board[stoneTwo] != field->squareIsFree)
{
// reset warning if necessary // reset warning if necessary
if (field->board[field->neighbour[stoneThree][0][0]] == field->curPlayer->id && field->board[field->neighbour[stoneThree][0][1]] == field->curPlayer->id) if (field->board[field->neighbour[stoneThree][0][0]] == field->curPlayer->id && field->board[field->neighbour[stoneThree][0][1]] == field->curPlayer->id)
@ -422,8 +389,7 @@ inline void MiniMaxAI::updateWarning(unsigned int firstStone, unsigned int secon
bool atLeastOneStoneRemoveAble = false; bool atLeastOneStoneRemoveAble = false;
if (field->stoneMustBeRemoved) if (field->stoneMustBeRemoved)
for (i = 0; i < field->size; i++) for (i = 0; i < field->size; i++)
if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) {
{
atLeastOneStoneRemoveAble = true; atLeastOneStoneRemoveAble = true;
break; break;
} }
@ -441,22 +407,19 @@ inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwne
unsigned int neighbor, direction; unsigned int neighbor, direction;
// look into every direction // look into every direction
for (direction = 0; direction < 4; direction++) for (direction = 0; direction < 4; direction++) {
{
neighbor = field->connectedSquare[stone][direction]; neighbor = field->connectedSquare[stone][direction];
// neighbor must exist // neighbor must exist
if (neighbor < field->size) if (neighbor < field->size) {
{
// relevant when moving from one square to another connected square // relevant when moving from one square to another connected square
if (ignoreStone == neighbor) if (ignoreStone == neighbor)
continue; continue;
// if there is no neighbour stone than it only affects the actual stone // if there is no neighbour stone than it only affects the actual stone
if (field->board[neighbor] == field->squareIsFree) if (field->board[neighbor] == field->squareIsFree) {
{
if (stoneRemoved) if (stoneRemoved)
stoneOwner->numPossibleMoves--; stoneOwner->numPossibleMoves--;
@ -464,17 +427,13 @@ inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwne
stoneOwner->numPossibleMoves++; stoneOwner->numPossibleMoves++;
// if there is a neighbour stone than it effects only this one // if there is a neighbour stone than it effects only this one
} } else if (field->board[neighbor] == field->curPlayer->id) {
else if (field->board[neighbor] == field->curPlayer->id)
{
if (stoneRemoved) if (stoneRemoved)
field->curPlayer->numPossibleMoves++; field->curPlayer->numPossibleMoves++;
else else
field->curPlayer->numPossibleMoves--; field->curPlayer->numPossibleMoves--;
} } else {
else
{
if (stoneRemoved) if (stoneRemoved)
field->oppPlayer->numPossibleMoves++; field->oppPlayer->numPossibleMoves++;
@ -602,23 +561,17 @@ void MiniMaxAI::move(unsigned int threadNo, unsigned int idPossibility, bool opp
curSearchDepth++; curSearchDepth++;
// very expensive // very expensive
for (i = 0; i < field->size; i++) for (i = 0; i < field->size; i++) {
{
oldState->stonePartOfMill[i] = field->stonePartOfMill[i]; oldState->stonePartOfMill[i] = field->stonePartOfMill[i];
oldState->warnings[i] = field->warnings[i]; oldState->warnings[i] = field->warnings[i];
} }
// move // move
if (field->stoneMustBeRemoved) if (field->stoneMustBeRemoved) {
{
removeStone(idPossibility, oldState); removeStone(idPossibility, oldState);
} } else if (field->settingPhase) {
else if (field->settingPhase)
{
setStone(idPossibility, oldState); setStone(idPossibility, oldState);
} } else {
else
{
normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState); normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState);
} }
@ -639,8 +592,7 @@ void MiniMaxAI::move(unsigned int threadNo, unsigned int idPossibility, bool opp
currentValue = VALUE_GAME_LOST + curSearchDepth; currentValue = VALUE_GAME_LOST + curSearchDepth;
// set next player // set next player
if (!field->stoneMustBeRemoved) if (!field->stoneMustBeRemoved) {
{
tmpPlayer = field->curPlayer; tmpPlayer = field->curPlayer;
field->curPlayer = field->oppPlayer; field->curPlayer = field->oppPlayer;
field->oppPlayer = tmpPlayer; field->oppPlayer = tmpPlayer;

View File

@ -44,15 +44,12 @@ MiniMax::MiniMax()
numWriteSkvOperations = 0; numWriteSkvOperations = 0;
numReadPlyOperations = 0; numReadPlyOperations = 0;
numWritePlyOperations = 0; numWritePlyOperations = 0;
if (MEASURE_ONLY_IO) if (MEASURE_ONLY_IO) {
{
readSkvInterval.QuadPart = 0; readSkvInterval.QuadPart = 0;
writeSkvInterval.QuadPart = 0; writeSkvInterval.QuadPart = 0;
readPlyInterval.QuadPart = 0; readPlyInterval.QuadPart = 0;
writePlyInterval.QuadPart = 0; writePlyInterval.QuadPart = 0;
} } else {
else
{
QueryPerformanceCounter(&readSkvInterval); QueryPerformanceCounter(&readSkvInterval);
QueryPerformanceCounter(&writeSkvInterval); QueryPerformanceCounter(&writeSkvInterval);
QueryPerformanceCounter(&readPlyInterval); QueryPerformanceCounter(&readPlyInterval);
@ -147,8 +144,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
prepareDatabaseCalculation(); prepareDatabaseCalculation();
// when database not completed then do it // when database not completed then do it
if (hFileShortKnotValues != nullptr && skvfHeader.completed == false) if (hFileShortKnotValues != nullptr && skvfHeader.completed == false) {
{
// reserve memory // reserve memory
lastCalculatedLayer.clear(); lastCalculatedLayer.clear();
@ -159,8 +155,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
arrayInfos.vectorArrays.resize(ArrayInfo::numArrayTypes * skvfHeader.numLayers, arrayInfos.listArrays.end()); arrayInfos.vectorArrays.resize(ArrayInfo::numArrayTypes * skvfHeader.numLayers, arrayInfos.listArrays.end());
// calc layer after layer, beginning with the last one // calc layer after layer, beginning with the last one
for (curCalculatedLayer = 0; curCalculatedLayer < skvfHeader.numLayers; curCalculatedLayer++) for (curCalculatedLayer = 0; curCalculatedLayer < skvfHeader.numLayers; curCalculatedLayer++) {
{
// layer already calculated? // layer already calculated?
if (layerStats[curCalculatedLayer].layerIsCompletedAndInFile) if (layerStats[curCalculatedLayer].layerIsCompletedAndInFile)
@ -191,8 +186,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
// don't save layer and header when only preparing layers or when // don't save layer and header when only preparing layers or when
if (onlyPrepareLayer) if (onlyPrepareLayer)
return; return;
if (!abortCalculation) if (!abortCalculation) {
{
// calc layer statistics // calc layer statistics
calcLayerStatistics("statistics.txt"); calcLayerStatistics("statistics.txt");
@ -206,9 +200,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
// free mem // free mem
curCalculationActionId = MM_ACTION_NONE; curCalculationActionId = MM_ACTION_NONE;
} } else {
else
{
PRINT(1, this, "\nThe database is already fully calculated.\n"); PRINT(1, this, "\nThe database is already fully calculated.\n");
} }
@ -230,8 +222,7 @@ bool MiniMax::calcLayer(unsigned int layerNumber)
vector<unsigned int> layersToCalculate; vector<unsigned int> layersToCalculate;
// moves can be done reverse, leading to too depth searching trees // moves can be done reverse, leading to too depth searching trees
if (shallRetroAnalysisBeUsed(layerNumber)) if (shallRetroAnalysisBeUsed(layerNumber)) {
{
// calc values for all states of layer // calc values for all states of layer
layersToCalculate.push_back(layerNumber); layersToCalculate.push_back(layerNumber);
@ -241,15 +232,12 @@ bool MiniMax::calcLayer(unsigned int layerNumber)
return false; return false;
// save partner layer // save partner layer
if (layerStats[layerNumber].partnerLayer != layerNumber) if (layerStats[layerNumber].partnerLayer != layerNumber) {
{
saveLayerToFile(layerStats[layerNumber].partnerLayer); saveLayerToFile(layerStats[layerNumber].partnerLayer);
} }
// use minimax-algorithm // use minimax-algorithm
} } else {
else
{
if (!calcKnotValuesByAlphaBeta(layerNumber)) if (!calcKnotValuesByAlphaBeta(layerNumber))
return false; return false;
} }
@ -258,17 +246,14 @@ bool MiniMax::calcLayer(unsigned int layerNumber)
saveLayerToFile(layerNumber); saveLayerToFile(layerNumber);
// test layer // test layer
if (!testLayer(layerNumber)) if (!testLayer(layerNumber)) {
{
PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl);
return false; return false;
} }
// test partner layer if retro-analysis has been used // test partner layer if retro-analysis has been used
if (shallRetroAnalysisBeUsed(layerNumber) && layerStats[layerNumber].partnerLayer != layerNumber) if (shallRetroAnalysisBeUsed(layerNumber) && layerStats[layerNumber].partnerLayer != layerNumber) {
{ if (!testLayer(layerStats[layerNumber].partnerLayer)) {
if (!testLayer(layerStats[layerNumber].partnerLayer))
{
PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl);
return false; return false;
} }
@ -276,8 +261,7 @@ bool MiniMax::calcLayer(unsigned int layerNumber)
// update output information // update output information
EnterCriticalSection(&csOsPrint); EnterCriticalSection(&csOsPrint);
if (shallRetroAnalysisBeUsed(layerNumber) && layerNumber != layerStats[layerNumber].partnerLayer) if (shallRetroAnalysisBeUsed(layerNumber) && layerNumber != layerStats[layerNumber].partnerLayer) {
{
lastCalculatedLayer.push_back(layerStats[layerNumber].partnerLayer); lastCalculatedLayer.push_back(layerStats[layerNumber].partnerLayer);
} }
lastCalculatedLayer.push_back(layerNumber); lastCalculatedLayer.push_back(layerNumber);

View File

@ -303,7 +303,9 @@ public:
while (true) while (true)
; ;
}; };
virtual void storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, TwoBit value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo){}; virtual void storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, TwoBit value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo)
{
};
virtual void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities) virtual void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities)
{ {
while (true) while (true)
@ -451,15 +453,13 @@ private:
AlphaBetaGlobalVars(MiniMax *pMiniMax, unsigned int layerNumber) AlphaBetaGlobalVars(MiniMax *pMiniMax, unsigned int layerNumber)
{ {
this->thread.resize(pMiniMax->threadManager.getNumThreads()); this->thread.resize(pMiniMax->threadManager.getNumThreads());
for (unsigned int threadNo = 0; threadNo < pMiniMax->threadManager.getNumThreads(); threadNo++) for (unsigned int threadNo = 0; threadNo < pMiniMax->threadManager.getNumThreads(); threadNo++) {
{
this->thread[threadNo].numStatesToProcess = 0; this->thread[threadNo].numStatesToProcess = 0;
this->thread[threadNo].threadNo = threadNo; this->thread[threadNo].threadNo = threadNo;
} }
this->layerNumber = layerNumber; this->layerNumber = layerNumber;
this->pMiniMax = pMiniMax; this->pMiniMax = pMiniMax;
if (pMiniMax->layerStats) if (pMiniMax->layerStats) {
{
this->numKnotsToCalc = pMiniMax->layerStats[layerNumber].knotsInLayer; this->numKnotsToCalc = pMiniMax->layerStats[layerNumber].knotsInLayer;
this->totalNumKnots = pMiniMax->layerStats[layerNumber].knotsInLayer; this->totalNumKnots = pMiniMax->layerStats[layerNumber].knotsInLayer;
} }
@ -478,23 +478,23 @@ private:
LONGLONG statesProcessed; LONGLONG statesProcessed;
unsigned int statsValueCounter[SKV_NUM_VALUES]; unsigned int statsValueCounter[SKV_NUM_VALUES];
AlphaBetaDefaultThreadVars(){}; AlphaBetaDefaultThreadVars()
{
};
AlphaBetaDefaultThreadVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) AlphaBetaDefaultThreadVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber)
{ {
this->statesProcessed = 0; this->statesProcessed = 0;
this->layerNumber = layerNumber; this->layerNumber = layerNumber;
this->pMiniMax = pMiniMax; this->pMiniMax = pMiniMax;
this->alphaBetaVars = alphaBetaVars; this->alphaBetaVars = alphaBetaVars;
for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) {
{
this->statsValueCounter[curStateValue] = 0; this->statsValueCounter[curStateValue] = 0;
} }
}; };
void reduceDefault() void reduceDefault()
{ {
pMiniMax->numStatesProcessed += this->statesProcessed; pMiniMax->numStatesProcessed += this->statesProcessed;
for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) {
{
alphaBetaVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; alphaBetaVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue];
} }
}; };
@ -505,7 +505,9 @@ private:
BufferedFile *bufferedFile; BufferedFile *bufferedFile;
bool initAlreadyDone; bool initAlreadyDone;
InitAlphaBetaVars(){}; InitAlphaBetaVars()
{
};
InitAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) InitAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
{ {
this->bufferedFile = initArray; this->bufferedFile = initArray;
@ -527,7 +529,9 @@ private:
unsigned int *freqValuesSubMovesBranchWon = nullptr; // ... unsigned int *freqValuesSubMovesBranchWon = nullptr; // ...
unsigned int freqValuesSubMoves[4]; // ... unsigned int freqValuesSubMoves[4]; // ...
RunAlphaBetaVars(){}; RunAlphaBetaVars()
{
};
RunAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) RunAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
{ {
initializeElement(*this); initializeElement(*this);
@ -585,23 +589,23 @@ private:
LONGLONG statesProcessed; LONGLONG statesProcessed;
unsigned int statsValueCounter[SKV_NUM_VALUES]; unsigned int statsValueCounter[SKV_NUM_VALUES];
RetroAnalysisDefaultThreadVars(){}; RetroAnalysisDefaultThreadVars()
{
};
RetroAnalysisDefaultThreadVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) RetroAnalysisDefaultThreadVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber)
{ {
this->statesProcessed = 0; this->statesProcessed = 0;
this->layerNumber = layerNumber; this->layerNumber = layerNumber;
this->pMiniMax = pMiniMax; this->pMiniMax = pMiniMax;
this->retroVars = retroVars; this->retroVars = retroVars;
for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) {
{
this->statsValueCounter[curStateValue] = 0; this->statsValueCounter[curStateValue] = 0;
} }
}; };
void reduceDefault() void reduceDefault()
{ {
pMiniMax->numStatesProcessed += this->statesProcessed; pMiniMax->numStatesProcessed += this->statesProcessed;
for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) {
{
retroVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; retroVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue];
} }
}; };
@ -612,7 +616,9 @@ private:
BufferedFile *bufferedFile; BufferedFile *bufferedFile;
bool initAlreadyDone; bool initAlreadyDone;
InitRetroAnalysisVars(){}; InitRetroAnalysisVars()
{
};
InitRetroAnalysisVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber) InitRetroAnalysisVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
{ {
this->bufferedFile = initArray; this->bufferedFile = initArray;
@ -632,8 +638,12 @@ private:
{ {
RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS];
AddNumSuccedorsVars(){}; AddNumSuccedorsVars()
AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber){}; {
};
AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
{
};
void initializeElement(AddNumSuccedorsVars &master) void initializeElement(AddNumSuccedorsVars &master)
{ {
*this = master; *this = master;

View File

@ -90,7 +90,9 @@ protected:
{ {
return 0; return 0;
}; };
void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers){}; void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers)
{
};
unsigned int getPartnerLayer(unsigned int layerNum) unsigned int getPartnerLayer(unsigned int layerNum)
{ {
return 0; return 0;
@ -99,7 +101,9 @@ protected:
{ {
return string(""); return string("");
}; };
void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel){}; void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel)
{
};
bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber)
{ {
return false; return false;
@ -116,11 +120,21 @@ protected:
{ {
return 0; return 0;
}; };
void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers){}; void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers)
void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars){}; {
void printBoard(unsigned int threadNo, unsigned char value){}; };
void prepareDatabaseCalculation(){}; void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars)
void wrapUpDatabaseCalculation(bool calculationAborted){}; {
};
void printBoard(unsigned int threadNo, unsigned char value)
{
};
void prepareDatabaseCalculation()
{
};
void wrapUpDatabaseCalculation(bool calculationAborted)
{
};
public: public:
// Constructor / destructor // Constructor / destructor

View File

@ -19,9 +19,15 @@
class MiniMaxGuiField class MiniMaxGuiField
{ {
public: public:
virtual void setAlignment(wildWeasel::alignment &newAlignment){}; virtual void setAlignment(wildWeasel::alignment &newAlignment)
virtual void setVisibility(bool visible){}; {
virtual void setState(unsigned int curShowedLayer, MiniMax::StateNumberVarType curShowedState){}; };
virtual void setVisibility(bool visible)
{
};
virtual void setState(unsigned int curShowedLayer, MiniMax::StateNumberVarType curShowedState)
{
};
}; };
/*------------------------------------------------------------------------------------ /*------------------------------------------------------------------------------------

View File

@ -23,15 +23,13 @@ bool MiniMax::calcKnotValuesByAlphaBeta(unsigned int layerNumber)
// initialization // initialization
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!initAlphaBeta(alphaBetaVars)) if (!initAlphaBeta(alphaBetaVars)) {
{
return false; return false;
} }
// run alpha-beta algorithmn // run alpha-beta algorithmn
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!runAlphaBeta(alphaBetaVars)) if (!runAlphaBeta(alphaBetaVars)) {
{
return false; return false;
} }
@ -69,8 +67,7 @@ void MiniMax::alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerN
savePlyInfoInDatabase(layerNumber, stateNumber, plyValue); savePlyInfoInDatabase(layerNumber, stateNumber, plyValue);
// save value for all symmetric states // save value for all symmetric states
for (i = 0; i < numSymmetricStates; i++) for (i = 0; i < numSymmetricStates; i++) {
{
// get state number // get state number
sysStateNumber = symStateNumbers[i]; sysStateNumber = symStateNumbers[i];
@ -109,8 +106,7 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
// does initialization file exist ? // does initialization file exist ?
CreateDirectoryA(ssInvArrayDirectory.str().c_str(), nullptr); CreateDirectoryA(ssInvArrayDirectory.str().c_str(), nullptr);
invalidArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInvArrayFilePath.str().c_str()); invalidArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInvArrayFilePath.str().c_str());
if (invalidArray->getFileSize() == (LONGLONG)layerStats[alphaBetaVars.layerNumber].knotsInLayer) if (invalidArray->getFileSize() == (LONGLONG)layerStats[alphaBetaVars.layerNumber].knotsInLayer) {
{
PRINT(2, this, " Loading invalid states from file: " << ssInvArrayFilePath.str()); PRINT(2, this, " Loading invalid states from file: " << ssInvArrayFilePath.str());
initAlreadyDone = true; initAlreadyDone = true;
} }
@ -124,8 +120,7 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
ThreadManager::ThreadVarsArray<InitAlphaBetaVars> tva(threadManager.getNumThreads(), InitAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber, invalidArray, initAlreadyDone)); ThreadManager::ThreadVarsArray<InitAlphaBetaVars> tva(threadManager.getNumThreads(), InitAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber, invalidArray, initAlreadyDone));
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeParallelLoop(initAlphaBetaThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[alphaBetaVars.layerNumber].knotsInLayer - 1, 1)) switch (threadManager.executeParallelLoop(initAlphaBetaThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[alphaBetaVars.layerNumber].knotsInLayer - 1, 1)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -141,8 +136,7 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
// reduce and delete thread specific data // reduce and delete thread specific data
tva.reduce(); tva.reduce();
if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) {
{
SAFE_DELETE(invalidArray); SAFE_DELETE(invalidArray);
return falseOrStop(); return falseOrStop();
} }
@ -180,47 +174,34 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index)
iabVars->statesProcessed++; iabVars->statesProcessed++;
// print status // print status
if (iabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (iabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states");
} }
// layer initialization already done ? if so, then read from file // layer initialization already done ? if so, then read from file
if (iabVars->initAlreadyDone) if (iabVars->initAlreadyDone) {
{ if (!iabVars->bufferedFile->readBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) {
if (!iabVars->bufferedFile->readBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue))
{
PRINT(0, m, "ERROR: initArray->takeBytes() failed"); PRINT(0, m, "ERROR: initArray->takeBytes() failed");
return m->falseOrStop(); return m->falseOrStop();
} }
// initialization not done // initialization not done
} } else {
else
{
// set current selected situation // set current selected situation
if (!m->setSituation(iabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) if (!m->setSituation(iabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
{
curStateValue = SKV_VALUE_INVALID; curStateValue = SKV_VALUE_INVALID;
} } else {
else
{
// get value of current situation // get value of current situation
m->getValueOfSituation(iabVars->curThreadNo, floatValue, curStateValue); m->getValueOfSituation(iabVars->curThreadNo, floatValue, curStateValue);
} }
} }
// calc ply info // calc ply info
if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) {
{
plyInfo = 0; plyInfo = 0;
} } else if (curStateValue == SKV_VALUE_INVALID) {
else if (curStateValue == SKV_VALUE_INVALID)
{
plyInfo = PLYINFO_VALUE_INVALID; plyInfo = PLYINFO_VALUE_INVALID;
} } else {
else
{
plyInfo = PLYINFO_VALUE_UNCALCULATED; plyInfo = PLYINFO_VALUE_UNCALCULATED;
} }
@ -229,10 +210,8 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index)
m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, plyInfo); m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, plyInfo);
// write data to file // write data to file
if (!iabVars->initAlreadyDone) if (!iabVars->initAlreadyDone) {
{ if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) {
if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue))
{
PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!");
return m->falseOrStop(); return m->falseOrStop();
} }
@ -261,8 +240,7 @@ bool MiniMax::runAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
threadManager.setNumThreads(1); threadManager.setNumThreads(1);
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeParallelLoop(runAlphaBetaThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[alphaBetaVars.layerNumber].knotsInLayer - 1, 1)) switch (threadManager.executeParallelLoop(runAlphaBetaThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[alphaBetaVars.layerNumber].knotsInLayer - 1, 1)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -307,8 +285,7 @@ DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index)
rabVars->statesProcessed++; rabVars->statesProcessed++;
// print status // print status
if (rabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (rabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(2, m, " Processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); PRINT(2, m, " Processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states");
} }
@ -319,14 +296,11 @@ DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index)
return TM_RETURN_VALUE_OK; return TM_RETURN_VALUE_OK;
// set current selected situation // set current selected situation
if (m->setSituation(rabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) if (m->setSituation(rabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
{
// calc value of situation // calc value of situation
m->letTheTreeGrow(&root, rabVars, m->depthOfFullTree, SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON); m->letTheTreeGrow(&root, rabVars, m->depthOfFullTree, SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON);
} } else {
else
{
// should not occur, because already tested by plyInfo == PLYINFO_VALUE_UNCALCULATED // should not occur, because already tested by plyInfo == PLYINFO_VALUE_UNCALCULATED
MessageBoxW(nullptr, L"This event should never occur. if (!m->setSituation())", L"ERROR", MB_OK); MessageBoxW(nullptr, L"This event should never occur. if (!m->setSituation())", L"ERROR", MB_OK);
} }
@ -357,25 +331,19 @@ void MiniMax::letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int
knot->floatValue = (float)knot->shortValue; knot->floatValue = (float)knot->shortValue;
// evaluate situation, musn't occur while calculating database // evaluate situation, musn't occur while calculating database
if (tilLevel == 0) if (tilLevel == 0) {
{ if (calcDatabase) {
if (calcDatabase)
{
// if tilLevel is equal zero it means that memory is gone out, since each recursive step needs memory // if tilLevel is equal zero it means that memory is gone out, since each recursive step needs memory
PRINT(0, this, "ERROR: tilLevel == 0"); PRINT(0, this, "ERROR: tilLevel == 0");
knot->shortValue = SKV_VALUE_INVALID; knot->shortValue = SKV_VALUE_INVALID;
knot->plyInfo = PLYINFO_VALUE_INVALID; knot->plyInfo = PLYINFO_VALUE_INVALID;
knot->floatValue = (float)knot->shortValue; knot->floatValue = (float)knot->shortValue;
falseOrStop(); falseOrStop();
} } else {
else
{
getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue); getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue);
} }
// investigate branches // investigate branches
} } else {
else
{
// get layer and state number of current state and look if short knot value can be found in database or in an array // get layer and state number of current state and look if short knot value can be found in database or in an array
if (alphaBetaTryDataBase(knot, rabVars, tilLevel, layerNumber, stateNumber)) if (alphaBetaTryDataBase(knot, rabVars, tilLevel, layerNumber, stateNumber))
@ -385,8 +353,7 @@ void MiniMax::letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int
idPossibility = getPossibilities(rabVars->curThreadNo, &knot->numPossibilities, &knot->isOpponentLevel, &pPossibilities); idPossibility = getPossibilities(rabVars->curThreadNo, &knot->numPossibilities, &knot->isOpponentLevel, &pPossibilities);
// unable to move // unable to move
if (knot->numPossibilities == 0) if (knot->numPossibilities == 0) {
{
// if unable to move a final state is reached // if unable to move a final state is reached
knot->plyInfo = 0; knot->plyInfo = 0;
@ -395,17 +362,14 @@ void MiniMax::letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int
rabVars->freqValuesSubMoves[knot->shortValue]++; rabVars->freqValuesSubMoves[knot->shortValue]++;
// if unable to move an invalid state was reached if nobody has won // if unable to move an invalid state was reached if nobody has won
if (calcDatabase && knot->shortValue == SKV_VALUE_GAME_DRAWN) if (calcDatabase && knot->shortValue == SKV_VALUE_GAME_DRAWN) {
{
knot->shortValue = SKV_VALUE_INVALID; knot->shortValue = SKV_VALUE_INVALID;
knot->plyInfo = PLYINFO_VALUE_INVALID; knot->plyInfo = PLYINFO_VALUE_INVALID;
knot->floatValue = (float)knot->shortValue; knot->floatValue = (float)knot->shortValue;
} }
// movement is possible // movement is possible
} } else {
else
{
// move, letTreeGroe, undo // move, letTreeGroe, undo
alphaBetaTryPossibilites(knot, rabVars, tilLevel, idPossibility, pPossibilities, maxWonfreqValuesSubMoves, alpha, beta); alphaBetaTryPossibilites(knot, rabVars, tilLevel, idPossibility, pPossibilities, maxWonfreqValuesSubMoves, alpha, beta);
@ -442,8 +406,7 @@ bool MiniMax::alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsign
PlyInfoVarType plyInfo = PLYINFO_VALUE_UNCALCULATED; PlyInfoVarType plyInfo = PLYINFO_VALUE_UNCALCULATED;
// use database ? // use database ?
if (hFilePlyInfo != nullptr && hFileShortKnotValues != nullptr && (calcDatabase || layerInDatabase)) if (hFilePlyInfo != nullptr && hFileShortKnotValues != nullptr && (calcDatabase || layerInDatabase)) {
{
// situation already existend in database ? // situation already existend in database ?
readKnotValueFromDatabase(rabVars->curThreadNo, layerNumber, stateNumber, shortKnotValue, invalidLayerOrStateNumber, subLayerInDatabaseAndCompleted); readKnotValueFromDatabase(rabVars->curThreadNo, layerNumber, stateNumber, shortKnotValue, invalidLayerOrStateNumber, subLayerInDatabaseAndCompleted);
@ -451,8 +414,7 @@ bool MiniMax::alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsign
// it was possible to achieve an invalid state using move(), // it was possible to achieve an invalid state using move(),
// so the original state was an invalid one // so the original state was an invalid one
if ((tilLevel < depthOfFullTree && invalidLayerOrStateNumber) || (tilLevel < depthOfFullTree && shortKnotValue == SKV_VALUE_INVALID && subLayerInDatabaseAndCompleted) || (tilLevel < depthOfFullTree && shortKnotValue == SKV_VALUE_INVALID && plyInfo != PLYINFO_VALUE_UNCALCULATED)) if ((tilLevel < depthOfFullTree && invalidLayerOrStateNumber) || (tilLevel < depthOfFullTree && shortKnotValue == SKV_VALUE_INVALID && subLayerInDatabaseAndCompleted) || (tilLevel < depthOfFullTree && shortKnotValue == SKV_VALUE_INVALID && plyInfo != PLYINFO_VALUE_UNCALCULATED)) { // version 22: replaced: curCalculatedLayer == layerNumber && knot->plyInfo != PLYINFO_VALUE_UNCALCULATED)) {
{ // version 22: replaced: curCalculatedLayer == layerNumber && knot->plyInfo != PLYINFO_VALUE_UNCALCULATED)) {
knot->shortValue = SKV_VALUE_INVALID; knot->shortValue = SKV_VALUE_INVALID;
knot->plyInfo = PLYINFO_VALUE_INVALID; knot->plyInfo = PLYINFO_VALUE_INVALID;
knot->floatValue = (float)knot->shortValue; knot->floatValue = (float)knot->shortValue;
@ -460,14 +422,12 @@ bool MiniMax::alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsign
} }
// print out put, if not calculating database, but requesting a knot value // print out put, if not calculating database, but requesting a knot value
if (shortKnotValue != SKV_VALUE_INVALID && tilLevel == depthOfFullTree && !calcDatabase && subLayerInDatabaseAndCompleted) if (shortKnotValue != SKV_VALUE_INVALID && tilLevel == depthOfFullTree && !calcDatabase && subLayerInDatabaseAndCompleted) {
{
PRINT(2, this, "This state is marked as " << ((shortKnotValue == SKV_VALUE_GAME_WON) ? "WON" : ((shortKnotValue == SKV_VALUE_GAME_LOST) ? "LOST" : ((shortKnotValue == SKV_VALUE_GAME_DRAWN) ? "DRAW" : "INVALID"))) << endl); PRINT(2, this, "This state is marked as " << ((shortKnotValue == SKV_VALUE_GAME_WON) ? "WON" : ((shortKnotValue == SKV_VALUE_GAME_LOST) ? "LOST" : ((shortKnotValue == SKV_VALUE_GAME_DRAWN) ? "DRAW" : "INVALID"))) << endl);
} }
// when knot value is valid then return best branch // when knot value is valid then return best branch
if (calcDatabase && tilLevel < depthOfFullTree && shortKnotValue != SKV_VALUE_INVALID && plyInfo != PLYINFO_VALUE_UNCALCULATED || !calcDatabase && tilLevel < depthOfFullTree - 1 && shortKnotValue != SKV_VALUE_INVALID) if (calcDatabase && tilLevel < depthOfFullTree && shortKnotValue != SKV_VALUE_INVALID && plyInfo != PLYINFO_VALUE_UNCALCULATED || !calcDatabase && tilLevel < depthOfFullTree - 1 && shortKnotValue != SKV_VALUE_INVALID) {
{
// switch if is not opponent level // switch if is not opponent level
if (knot->isOpponentLevel) if (knot->isOpponentLevel)
@ -492,12 +452,10 @@ void MiniMax::alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, un
void *pBackup; void *pBackup;
unsigned int curPoss; unsigned int curPoss;
for (curPoss = 0; curPoss < knot->numPossibilities; curPoss++) for (curPoss = 0; curPoss < knot->numPossibilities; curPoss++) {
{
// output // output
if (tilLevel == depthOfFullTree && !calcDatabase) if (tilLevel == depthOfFullTree && !calcDatabase) {
{
printMoveInformation(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities); printMoveInformation(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities);
rabVars->freqValuesSubMoves[SKV_VALUE_INVALID] = 0; rabVars->freqValuesSubMoves[SKV_VALUE_INVALID] = 0;
rabVars->freqValuesSubMoves[SKV_VALUE_GAME_LOST] = 0; rabVars->freqValuesSubMoves[SKV_VALUE_GAME_LOST] = 0;
@ -515,25 +473,18 @@ void MiniMax::alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, un
undo(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, pBackup, pPossibilities); undo(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, pBackup, pPossibilities);
// output // output
if (tilLevel == depthOfFullTree && !calcDatabase) if (tilLevel == depthOfFullTree && !calcDatabase) {
{
rabVars->freqValuesSubMovesBranchWon[curPoss] = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON]; rabVars->freqValuesSubMovesBranchWon[curPoss] = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON];
if (rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON] > maxWonfreqValuesSubMoves && knot->branches[curPoss].shortValue == SKV_VALUE_GAME_DRAWN) if (rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON] > maxWonfreqValuesSubMoves && knot->branches[curPoss].shortValue == SKV_VALUE_GAME_DRAWN) {
{
maxWonfreqValuesSubMoves = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON]; maxWonfreqValuesSubMoves = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON];
} }
if (hFileShortKnotValues != nullptr && layerInDatabase) if (hFileShortKnotValues != nullptr && layerInDatabase) {
{
storeValueOfMove(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities, knot->branches[curPoss].shortValue, rabVars->freqValuesSubMoves, knot->branches[curPoss].plyInfo); storeValueOfMove(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities, knot->branches[curPoss].shortValue, rabVars->freqValuesSubMoves, knot->branches[curPoss].plyInfo);
PRINT(0, this, "\t: " << ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_WON) ? "WON" : ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_LOST) ? "LOST" : ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_DRAWN) ? "DRAW" : "INVALID"))) << endl); PRINT(0, this, "\t: " << ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_WON) ? "WON" : ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_LOST) ? "LOST" : ((knot->branches[curPoss].shortValue == SKV_VALUE_GAME_DRAWN) ? "DRAW" : "INVALID"))) << endl);
} } else {
else
{
PRINT(0, this, "\t: " << knot->branches[curPoss].floatValue << endl); PRINT(0, this, "\t: " << knot->branches[curPoss].floatValue << endl);
} }
} } else if (tilLevel == depthOfFullTree - 1 && !calcDatabase) {
else if (tilLevel == depthOfFullTree - 1 && !calcDatabase)
{
rabVars->freqValuesSubMoves[knot->branches[curPoss].shortValue]++; rabVars->freqValuesSubMoves[knot->branches[curPoss].shortValue]++;
} }
@ -544,39 +495,27 @@ void MiniMax::alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, un
continue; continue;
// alpha beta algorithmn // alpha beta algorithmn
if (!knot->isOpponentLevel) if (!knot->isOpponentLevel) {
{ if (knot->branches[curPoss].floatValue >= beta) {
if (knot->branches[curPoss].floatValue >= beta)
{
knot->numPossibilities = curPoss + 1; knot->numPossibilities = curPoss + 1;
break; break;
} } else if (knot->branches[curPoss].floatValue > alpha) {
else if (knot->branches[curPoss].floatValue > alpha)
{
alpha = knot->branches[curPoss].floatValue; alpha = knot->branches[curPoss].floatValue;
} }
} } else {
else if (knot->branches[curPoss].floatValue <= alpha) {
{
if (knot->branches[curPoss].floatValue <= alpha)
{
knot->numPossibilities = curPoss + 1; knot->numPossibilities = curPoss + 1;
break; break;
} } else if (knot->branches[curPoss].floatValue < beta) {
else if (knot->branches[curPoss].floatValue < beta)
{
beta = knot->branches[curPoss].floatValue; beta = knot->branches[curPoss].floatValue;
} }
} }
} }
// let delete pPossibilities // let delete pPossibilities
if (tilLevel < depthOfFullTree) if (tilLevel < depthOfFullTree) {
{
deletePossibilities(rabVars->curThreadNo, pPossibilities); deletePossibilities(rabVars->curThreadNo, pPossibilities);
} } else {
else
{
pRootPossibilities = pPossibilities; pRootPossibilities = pPossibilities;
} }
} }
@ -593,25 +532,18 @@ void MiniMax::alphaBetaCalcKnotValue(Node *knot)
unsigned int i; unsigned int i;
// opponent tries to minimize the value // opponent tries to minimize the value
if (knot->isOpponentLevel) if (knot->isOpponentLevel) {
{ for (i = 1; i < knot->numPossibilities; i++) {
for (i = 1; i < knot->numPossibilities; i++)
{
// version 21: it should be impossible that knot->shortValue is equal SKV_VALUE_INVALID // version 21: it should be impossible that knot->shortValue is equal SKV_VALUE_INVALID
if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue < maxValue) if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue < maxValue) {
{
maxValue = knot->branches[i].floatValue; maxValue = knot->branches[i].floatValue;
maxBranch = i; maxBranch = i;
} }
} }
// maximize the value // maximize the value
} } else {
else for (i = 1; i < knot->numPossibilities; i++) {
{ if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue > maxValue) {
for (i = 1; i < knot->numPossibilities; i++)
{
if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue > maxValue)
{
maxValue = knot->branches[i].floatValue; maxValue = knot->branches[i].floatValue;
maxBranch = i; maxBranch = i;
} }
@ -636,16 +568,11 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot)
TwoBit shortKnotValue; TwoBit shortKnotValue;
// //
if (knot->shortValue == SKV_VALUE_GAME_DRAWN) if (knot->shortValue == SKV_VALUE_GAME_DRAWN) {
{
knot->plyInfo = PLYINFO_VALUE_DRAWN; knot->plyInfo = PLYINFO_VALUE_DRAWN;
} } else if (knot->shortValue == SKV_VALUE_INVALID) {
else if (knot->shortValue == SKV_VALUE_INVALID)
{
knot->plyInfo = PLYINFO_VALUE_INVALID; knot->plyInfo = PLYINFO_VALUE_INVALID;
} } else {
else
{
// calculate value of knot // calculate value of knot
shortKnotValue = (knot->isOpponentLevel) ? skvPerspectiveMatrix[knot->shortValue][PL_TO_MOVE_UNCHANGED] : knot->shortValue; shortKnotValue = (knot->isOpponentLevel) ? skvPerspectiveMatrix[knot->shortValue][PL_TO_MOVE_UNCHANGED] : knot->shortValue;
@ -653,11 +580,9 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot)
maxBranch = 0; maxBranch = 0;
// when current knot is a won state // when current knot is a won state
if (shortKnotValue == SKV_VALUE_GAME_WON) if (shortKnotValue == SKV_VALUE_GAME_WON) {
{
for (i = 0; i < knot->numPossibilities; i++) for (i = 0; i < knot->numPossibilities; i++) {
{
// invert knot value if necessary // invert knot value if necessary
shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue;
@ -666,8 +591,7 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot)
if ((knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel != knot->branches[i].isOpponentLevel) if ((knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel != knot->branches[i].isOpponentLevel)
// after this move the same player will continue, so take the minimum of the won states // after this move the same player will continue, so take the minimum of the won states
|| (knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) || (knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) {
{
maxPlyInfo = knot->branches[i].plyInfo; maxPlyInfo = knot->branches[i].plyInfo;
maxBranch = i; maxBranch = i;
@ -675,12 +599,9 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot)
} }
// current state is a lost state // current state is a lost state
} } else {
else
{
for (i = 0; i < knot->numPossibilities; i++) for (i = 0; i < knot->numPossibilities; i++) {
{
// invert knot value if necessary // invert knot value if necessary
shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue;
@ -689,8 +610,7 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot)
if ((knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel != knot->branches[i].isOpponentLevel) if ((knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel != knot->branches[i].isOpponentLevel)
// take the maximum of the won states, since that's the longest path // take the maximum of the won states, since that's the longest path
|| (knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) || (knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) {
{
maxPlyInfo = knot->branches[i].plyInfo; maxPlyInfo = knot->branches[i].plyInfo;
maxBranch = i; maxBranch = i;
@ -717,49 +637,37 @@ void MiniMax::alphaBetaChooseBestMove(Node *knot, RunAlphaBetaVars *rabVars, uns
unsigned int maxBranch; unsigned int maxBranch;
// select randomly one of the best moves, if they are equivalent // select randomly one of the best moves, if they are equivalent
if (tilLevel == depthOfFullTree && !calcDatabase) if (tilLevel == depthOfFullTree && !calcDatabase) {
{
// check every possible move // check every possible move
for (numBestChoices = 0, i = 0; i < knot->numPossibilities; i++) for (numBestChoices = 0, i = 0; i < knot->numPossibilities; i++) {
{
// use information in database // use information in database
if (layerInDatabase && hFileShortKnotValues != nullptr) if (layerInDatabase && hFileShortKnotValues != nullptr) {
{
// selected move with equal knot value // selected move with equal knot value
if (knot->branches[i].shortValue == knot->shortValue) if (knot->branches[i].shortValue == knot->shortValue) {
{
// best move lead to drawn state // best move lead to drawn state
if (knot->shortValue == SKV_VALUE_GAME_DRAWN) if (knot->shortValue == SKV_VALUE_GAME_DRAWN) {
{ if (maxWonfreqValuesSubMoves == rabVars->freqValuesSubMovesBranchWon[i]) {
if (maxWonfreqValuesSubMoves == rabVars->freqValuesSubMovesBranchWon[i])
{
bestBranches[numBestChoices] = i; bestBranches[numBestChoices] = i;
numBestChoices++; numBestChoices++;
} }
// best move lead to lost or won state // best move lead to lost or won state
} } else {
else if (knot->plyInfo == knot->branches[i].plyInfo + 1) {
{
if (knot->plyInfo == knot->branches[i].plyInfo + 1)
{
bestBranches[numBestChoices] = i; bestBranches[numBestChoices] = i;
numBestChoices++; numBestChoices++;
} }
} }
} }
// conventionell mini-max algorithm // conventionell mini-max algorithm
} } else {
else
{
dif = knot->branches[i].floatValue - knot->floatValue; dif = knot->branches[i].floatValue - knot->floatValue;
dif = (dif > 0) ? dif : -1.0f * dif; dif = (dif > 0) ? dif : -1.0f * dif;
if (dif < FPKV_THRESHOLD) if (dif < FPKV_THRESHOLD) {
{
bestBranches[numBestChoices] = i; bestBranches[numBestChoices] = i;
numBestChoices++; numBestChoices++;
} }

View File

@ -15,8 +15,7 @@
void MiniMax::closeDatabase() void MiniMax::closeDatabase()
{ {
// close database // close database
if (hFileShortKnotValues != nullptr) if (hFileShortKnotValues != nullptr) {
{
unloadAllLayers(); unloadAllLayers();
SAFE_DELETE_ARRAY(layerStats); SAFE_DELETE_ARRAY(layerStats);
CloseHandle(hFileShortKnotValues); CloseHandle(hFileShortKnotValues);
@ -24,8 +23,7 @@ void MiniMax::closeDatabase()
} }
// close ply information file // close ply information file
if (hFilePlyInfo != nullptr) if (hFilePlyInfo != nullptr) {
{
unloadAllPlyInfos(); unloadAllPlyInfos();
SAFE_DELETE_ARRAY(plyInfos); SAFE_DELETE_ARRAY(plyInfos);
CloseHandle(hFilePlyInfo); CloseHandle(hFilePlyInfo);
@ -65,8 +63,7 @@ void MiniMax::unloadLayer(unsigned int layerNumber)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MiniMax::unloadAllPlyInfos() void MiniMax::unloadAllPlyInfos()
{ {
for (unsigned int i = 0; i < plyInfoHeader.numLayers; i++) for (unsigned int i = 0; i < plyInfoHeader.numLayers; i++) {
{
unloadPlyInfo(i); unloadPlyInfo(i);
} }
} }
@ -77,8 +74,7 @@ void MiniMax::unloadAllPlyInfos()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MiniMax::unloadAllLayers() void MiniMax::unloadAllLayers()
{ {
for (unsigned int i = 0; i < skvfHeader.numLayers; i++) for (unsigned int i = 0; i < skvfHeader.numLayers; i++) {
{
unloadLayer(i); unloadLayer(i);
} }
} }
@ -97,23 +93,18 @@ void MiniMax::saveBytesToFile(HANDLE hFile, long long offset, unsigned int numBy
liDistanceToMove.QuadPart = offset; liDistanceToMove.QuadPart = offset;
while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) {
{
if (!errorPrint) if (!errorPrint)
PRINT(1, this, "ERROR: SetFilePointerEx failed!"); PRINT(1, this, "ERROR: SetFilePointerEx failed!");
} }
while (restingBytes > 0) while (restingBytes > 0) {
{ if (WriteFile(hFile, myPointer, restingBytes, &dwBytesWritten, nullptr) == TRUE) {
if (WriteFile(hFile, myPointer, restingBytes, &dwBytesWritten, nullptr) == TRUE)
{
restingBytes -= dwBytesWritten; restingBytes -= dwBytesWritten;
myPointer = (void *)(((unsigned char *)myPointer) + dwBytesWritten); myPointer = (void *)(((unsigned char *)myPointer) + dwBytesWritten);
if (restingBytes > 0) if (restingBytes > 0)
PRINT(2, this, "Still " << restingBytes << " to write!"); PRINT(2, this, "Still " << restingBytes << " to write!");
} } else {
else
{
if (!errorPrint) if (!errorPrint)
PRINT(0, this, "ERROR: WriteFile Failed!"); PRINT(0, this, "ERROR: WriteFile Failed!");
errorPrint = true; errorPrint = true;
@ -135,25 +126,19 @@ void MiniMax::loadBytesFromFile(HANDLE hFile, long long offset, unsigned int num
liDistanceToMove.QuadPart = offset; liDistanceToMove.QuadPart = offset;
while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) {
{
if (!errorPrint) if (!errorPrint)
PRINT(0, this, "ERROR: SetFilePointerEx failed!"); PRINT(0, this, "ERROR: SetFilePointerEx failed!");
} }
while (restingBytes > 0) while (restingBytes > 0) {
{ if (ReadFile(hFile, pBytes, restingBytes, &dwBytesRead, nullptr) == TRUE) {
if (ReadFile(hFile, pBytes, restingBytes, &dwBytesRead, nullptr) == TRUE)
{
restingBytes -= dwBytesRead; restingBytes -= dwBytesRead;
myPointer = (void *)(((unsigned char *)myPointer) + dwBytesRead); myPointer = (void *)(((unsigned char *)myPointer) + dwBytesRead);
if (restingBytes > 0) if (restingBytes > 0) {
{
PRINT(2, this, "Still " << restingBytes << " bytes to read!"); PRINT(2, this, "Still " << restingBytes << " bytes to read!");
} }
} } else {
else
{
if (!errorPrint) if (!errorPrint)
PRINT(0, this, "ERROR: ReadFile Failed!"); PRINT(0, this, "ERROR: ReadFile Failed!");
errorPrint = true; errorPrint = true;
@ -169,12 +154,9 @@ bool MiniMax::isCurrentStateInDatabase(unsigned int threadNo)
{ {
unsigned int layerNum, stateNumber; unsigned int layerNum, stateNumber;
if (hFileShortKnotValues == nullptr) if (hFileShortKnotValues == nullptr) {
{
return false; return false;
} } else {
else
{
getLayerAndStateNumber(threadNo, layerNum, stateNumber); getLayerAndStateNumber(threadNo, layerNum, stateNumber);
return layerStats[layerNum].layerIsCompletedAndInFile; return layerStats[layerNum].layerIsCompletedAndInFile;
} }
@ -210,8 +192,7 @@ void MiniMax::saveHeader(PlyInfoFileHeader *piH, PlyInfo *pInfo)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool MiniMax::openDatabase(const char *directory, unsigned int maximumNumberOfBranches) bool MiniMax::openDatabase(const char *directory, unsigned int maximumNumberOfBranches)
{ {
if (strlen(directory) && !PathFileExistsA(directory)) if (strlen(directory) && !PathFileExistsA(directory)) {
{
PRINT(0, this, "ERROR: Database path " << directory << " not valid!"); PRINT(0, this, "ERROR: Database path " << directory << " not valid!");
return falseOrStop(); return falseOrStop();
} }
@ -244,8 +225,7 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra
hFileShortKnotValues = CreateFileA(ssDatabaseFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hFileShortKnotValues = CreateFileA(ssDatabaseFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hFileShortKnotValues == INVALID_HANDLE_VALUE) if (hFileShortKnotValues == INVALID_HANDLE_VALUE) {
{
hFileShortKnotValues = nullptr; hFileShortKnotValues = nullptr;
return; return;
} }
@ -258,8 +238,7 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra
ReadFile(hFileShortKnotValues, &skvfHeader, sizeof(SkvFileHeader), &dwBytesRead, nullptr); ReadFile(hFileShortKnotValues, &skvfHeader, sizeof(SkvFileHeader), &dwBytesRead, nullptr);
// invalid file ? // invalid file ?
if (dwBytesRead != sizeof(SkvFileHeader) || skvfHeader.headerCode != SKV_FILE_HEADER_CODE) if (dwBytesRead != sizeof(SkvFileHeader) || skvfHeader.headerCode != SKV_FILE_HEADER_CODE) {
{
// create default header // create default header
skvfHeader.completed = false; skvfHeader.completed = false;
@ -269,8 +248,7 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra
layerStats = new LayerStats[skvfHeader.numLayers]; layerStats = new LayerStats[skvfHeader.numLayers];
layerStats[0].layerOffset = 0; layerStats[0].layerOffset = 0;
for (i = 0; i < skvfHeader.numLayers; i++) for (i = 0; i < skvfHeader.numLayers; i++) {
{
getSuccLayers(i, &layerStats[i].numSuccLayers, &layerStats[i].succLayers[0]); getSuccLayers(i, &layerStats[i].numSuccLayers, &layerStats[i].succLayers[0]);
layerStats[i].partnerLayer = getPartnerLayer(i); layerStats[i].partnerLayer = getPartnerLayer(i);
layerStats[i].knotsInLayer = getNumberOfKnotsInLayer(i); layerStats[i].knotsInLayer = getNumberOfKnotsInLayer(i);
@ -285,8 +263,7 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra
layerStats[i].numInvalidStates = 0; layerStats[i].numInvalidStates = 0;
} }
for (i = 1; i < skvfHeader.numLayers; i++) for (i = 1; i < skvfHeader.numLayers; i++) {
{
layerStats[i].layerOffset = layerStats[i - 1].layerOffset + layerStats[i - 1].sizeInBytes; layerStats[i].layerOffset = layerStats[i - 1].layerOffset + layerStats[i - 1].sizeInBytes;
} }
@ -294,13 +271,10 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra
saveHeader(&skvfHeader, layerStats); saveHeader(&skvfHeader, layerStats);
// read layer stats // read layer stats
} } else {
else
{
layerStats = new LayerStats[skvfHeader.numLayers]; layerStats = new LayerStats[skvfHeader.numLayers];
ReadFile(hFileShortKnotValues, layerStats, sizeof(LayerStats) * skvfHeader.numLayers, &dwBytesRead, nullptr); ReadFile(hFileShortKnotValues, layerStats, sizeof(LayerStats) * skvfHeader.numLayers, &dwBytesRead, nullptr);
for (i = 0; i < skvfHeader.numLayers; i++) for (i = 0; i < skvfHeader.numLayers; i++) {
{
layerStats[i].shortKnotValueByte = nullptr; layerStats[i].shortKnotValueByte = nullptr;
layerStats[i].skvCompressed = nullptr; layerStats[i].skvCompressed = nullptr;
} }
@ -331,8 +305,7 @@ void MiniMax::openPlyInfoFile(const char *directory)
hFilePlyInfo = CreateFileA(ssFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hFilePlyInfo = CreateFileA(ssFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully // opened file succesfully
if (hFilePlyInfo == INVALID_HANDLE_VALUE) if (hFilePlyInfo == INVALID_HANDLE_VALUE) {
{
hFilePlyInfo = nullptr; hFilePlyInfo = nullptr;
return; return;
} }
@ -344,8 +317,7 @@ void MiniMax::openPlyInfoFile(const char *directory)
ReadFile(hFilePlyInfo, &plyInfoHeader, sizeof(plyInfoHeader), &dwBytesRead, nullptr); ReadFile(hFilePlyInfo, &plyInfoHeader, sizeof(plyInfoHeader), &dwBytesRead, nullptr);
// invalid file ? // invalid file ?
if (dwBytesRead != sizeof(plyInfoHeader) || plyInfoHeader.headerCode != PLYINFO_HEADER_CODE) if (dwBytesRead != sizeof(plyInfoHeader) || plyInfoHeader.headerCode != PLYINFO_HEADER_CODE) {
{
// create default header // create default header
plyInfoHeader.plyInfoCompleted = false; plyInfoHeader.plyInfoCompleted = false;
@ -355,8 +327,7 @@ void MiniMax::openPlyInfoFile(const char *directory)
plyInfos = new PlyInfo[plyInfoHeader.numLayers]; plyInfos = new PlyInfo[plyInfoHeader.numLayers];
plyInfos[0].layerOffset = 0; plyInfos[0].layerOffset = 0;
for (i = 0; i < plyInfoHeader.numLayers; i++) for (i = 0; i < plyInfoHeader.numLayers; i++) {
{
plyInfos[i].knotsInLayer = getNumberOfKnotsInLayer(i); plyInfos[i].knotsInLayer = getNumberOfKnotsInLayer(i);
plyInfos[i].plyInfo = nullptr; plyInfos[i].plyInfo = nullptr;
plyInfos[i].plyInfoCompressed = nullptr; plyInfos[i].plyInfoCompressed = nullptr;
@ -365,8 +336,7 @@ void MiniMax::openPlyInfoFile(const char *directory)
plyInfos[i].sizeInBytes = plyInfos[i].knotsInLayer * sizeof(PlyInfoVarType); plyInfos[i].sizeInBytes = plyInfos[i].knotsInLayer * sizeof(PlyInfoVarType);
} }
for (i = 1; i < plyInfoHeader.numLayers; i++) for (i = 1; i < plyInfoHeader.numLayers; i++) {
{
plyInfos[i].layerOffset = plyInfos[i - 1].layerOffset + plyInfos[i - 1].sizeInBytes; plyInfos[i].layerOffset = plyInfos[i - 1].layerOffset + plyInfos[i - 1].sizeInBytes;
} }
@ -374,13 +344,10 @@ void MiniMax::openPlyInfoFile(const char *directory)
saveHeader(&plyInfoHeader, plyInfos); saveHeader(&plyInfoHeader, plyInfos);
// read layer stats // read layer stats
} } else {
else
{
plyInfos = new PlyInfo[plyInfoHeader.numLayers]; plyInfos = new PlyInfo[plyInfoHeader.numLayers];
ReadFile(hFilePlyInfo, plyInfos, sizeof(PlyInfo) * plyInfoHeader.numLayers, &dwBytesRead, nullptr); ReadFile(hFilePlyInfo, plyInfos, sizeof(PlyInfo) * plyInfoHeader.numLayers, &dwBytesRead, nullptr);
for (i = 0; i < plyInfoHeader.numLayers; i++) for (i = 0; i < plyInfoHeader.numLayers; i++) {
{
plyInfos[i].plyInfo = nullptr; plyInfos[i].plyInfo = nullptr;
plyInfos[i].plyInfoCompressed = nullptr; plyInfos[i].plyInfoCompressed = nullptr;
} }
@ -400,8 +367,7 @@ void MiniMax::saveLayerToFile(unsigned int layerNumber)
return; return;
// save layer if there are any states // save layer if there are any states
if (myLss->sizeInBytes) if (myLss->sizeInBytes) {
{
// short knot values & ply info // short knot values & ply info
curCalculationActionId = MM_ACTION_SAVING_LAYER_TO_FILE; curCalculationActionId = MM_ACTION_SAVING_LAYER_TO_FILE;
@ -428,21 +394,17 @@ inline void MiniMax::measureIops(long long &numOperations, LARGE_INTEGER &interv
numOperations++; // ... not thread-safe !!! numOperations++; // ... not thread-safe !!!
// only the time for the io-operation is considered and accumulated // only the time for the io-operation is considered and accumulated
if (MEASURE_ONLY_IO) if (MEASURE_ONLY_IO) {
{
QueryPerformanceCounter(&curTimeAfter); QueryPerformanceCounter(&curTimeAfter);
interval.QuadPart += curTimeAfter.QuadPart - curTimeBefore.QuadPart; // ... not thread-safe !!! interval.QuadPart += curTimeAfter.QuadPart - curTimeBefore.QuadPart; // ... not thread-safe !!!
double totalTimeGone = (double)interval.QuadPart / frequency.QuadPart; // ... not thread-safe !!! double totalTimeGone = (double)interval.QuadPart / frequency.QuadPart; // ... not thread-safe !!!
if (totalTimeGone >= 5.0) if (totalTimeGone >= 5.0) {
{
PRINT(0, this, text << "operations per second for last interval: " << (int)(numOperations / totalTimeGone)); PRINT(0, this, text << "operations per second for last interval: " << (int)(numOperations / totalTimeGone));
interval.QuadPart = 0; // ... not thread-safe !!! interval.QuadPart = 0; // ... not thread-safe !!!
numOperations = 0; // ... not thread-safe !!! numOperations = 0; // ... not thread-safe !!!
} }
// the whole time passed since the beginning of the interval is considered // the whole time passed since the beginning of the interval is considered
} } else if (numOperations >= MEASURE_TIME_FREQUENCY) {
else if (numOperations >= MEASURE_TIME_FREQUENCY)
{
QueryPerformanceCounter(&curTimeAfter); QueryPerformanceCounter(&curTimeAfter);
double totalTimeGone = (double)(curTimeAfter.QuadPart - interval.QuadPart) / frequency.QuadPart; // ... not thread-safe !!! double totalTimeGone = (double)(curTimeAfter.QuadPart - interval.QuadPart) / frequency.QuadPart; // ... not thread-safe !!!
PRINT(0, this, text << "operations per second for last interval: " << numOperations / totalTimeGone); PRINT(0, this, text << "operations per second for last interval: " << numOperations / totalTimeGone);
@ -465,17 +427,13 @@ void MiniMax::readKnotValueFromDatabase(unsigned int threadNo, unsigned int &lay
layerInDatabaseAndCompleted = myLss->layerIsCompletedAndInFile; layerInDatabaseAndCompleted = myLss->layerIsCompletedAndInFile;
// valid state and layer number ? // valid state and layer number ?
if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) {
{
invalidLayerOrStateNumber = true; invalidLayerOrStateNumber = true;
} } else {
else
{
invalidLayerOrStateNumber = false; // checkStateIntegrity(); invalidLayerOrStateNumber = false; // checkStateIntegrity();
} }
if (invalidLayerOrStateNumber) if (invalidLayerOrStateNumber) {
{
knotValue = SKV_VALUE_INVALID; knotValue = SKV_VALUE_INVALID;
return; return;
} }
@ -497,38 +455,29 @@ void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int s
LayerStats *myLss = &layerStats[layerNumber]; LayerStats *myLss = &layerStats[layerNumber];
// valid state and layer number ? // valid state and layer number ?
if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) {
{
PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readKnotValueFromDatabase()!"); PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readKnotValueFromDatabase()!");
knotValue = SKV_VALUE_INVALID; knotValue = SKV_VALUE_INVALID;
return; return;
} }
// if database is complete get whole byte from file // if database is complete get whole byte from file
if (skvfHeader.completed || layerInDatabase || myLss->layerIsCompletedAndInFile) if (skvfHeader.completed || layerInDatabase || myLss->layerIsCompletedAndInFile) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset + stateNumber / 4, 1, &databaseByte); loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset + stateNumber / 4, 1, &databaseByte);
LeaveCriticalSection(&csDatabase); LeaveCriticalSection(&csDatabase);
} } else {
else
{
// is layer already loaded // is layer already loaded
if (!myLss->layerIsLoaded) if (!myLss->layerIsLoaded) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
if (!myLss->layerIsLoaded) if (!myLss->layerIsLoaded) {
{
// if layer is in database and completed, then load layer from file into memory, set default value otherwise // if layer is in database and completed, then load layer from file into memory, set default value otherwise
myLss->shortKnotValueByte = new unsigned char[myLss->sizeInBytes]; myLss->shortKnotValueByte = new unsigned char[myLss->sizeInBytes];
if (myLss->layerIsCompletedAndInFile) if (myLss->layerIsCompletedAndInFile) {
{
loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte); loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte);
} } else {
else
{
memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes);
} }
bytesAllocated = myLss->sizeInBytes; bytesAllocated = myLss->sizeInBytes;
@ -544,8 +493,7 @@ void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int s
// measure io-operations per second // measure io-operations per second
LARGE_INTEGER curTimeBefore; LARGE_INTEGER curTimeBefore;
if (MEASURE_IOPS && MEASURE_ONLY_IO) if (MEASURE_IOPS && MEASURE_ONLY_IO) {
{
QueryPerformanceCounter(&curTimeBefore); QueryPerformanceCounter(&curTimeBefore);
} }
@ -573,39 +521,29 @@ void MiniMax::readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int sta
PlyInfo *myPis = &plyInfos[layerNumber]; PlyInfo *myPis = &plyInfos[layerNumber];
// valid state and layer number ? // valid state and layer number ?
if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) {
{
PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readPlyInfoFromDatabase()!"); PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readPlyInfoFromDatabase()!");
value = PLYINFO_VALUE_INVALID; value = PLYINFO_VALUE_INVALID;
return; return;
} }
// if database is complete get whole byte from file // if database is complete get whole byte from file
if (plyInfoHeader.plyInfoCompleted || layerInDatabase || myPis->plyInfoIsCompletedAndInFile) if (plyInfoHeader.plyInfoCompleted || layerInDatabase || myPis->plyInfoIsCompletedAndInFile) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset + sizeof(PlyInfoVarType) * stateNumber, sizeof(PlyInfoVarType), &value); loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset + sizeof(PlyInfoVarType) * stateNumber, sizeof(PlyInfoVarType), &value);
LeaveCriticalSection(&csDatabase); LeaveCriticalSection(&csDatabase);
} } else {
else
{
// is layer already in memory? // is layer already in memory?
if (!myPis->plyInfoIsLoaded) if (!myPis->plyInfoIsLoaded) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
if (!myPis->plyInfoIsLoaded) if (!myPis->plyInfoIsLoaded) {
{
// if layer is in database and completed, then load layer from file into memory; set default value otherwise // if layer is in database and completed, then load layer from file into memory; set default value otherwise
myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer];
if (myPis->plyInfoIsCompletedAndInFile) if (myPis->plyInfoIsCompletedAndInFile) {
{
loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo); loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo);
} } else {
else for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) {
{
for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++)
{
myPis->plyInfo[curKnot] = defValue; myPis->plyInfo[curKnot] = defValue;
} }
} }
@ -620,8 +558,7 @@ void MiniMax::readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int sta
// measure io-operations per second // measure io-operations per second
LARGE_INTEGER curTimeBefore; LARGE_INTEGER curTimeBefore;
if (MEASURE_IOPS && MEASURE_ONLY_IO) if (MEASURE_IOPS && MEASURE_ONLY_IO) {
{
QueryPerformanceCounter(&curTimeBefore); QueryPerformanceCounter(&curTimeBefore);
} }
@ -645,26 +582,22 @@ void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int sta
LayerStats *myLss = &layerStats[layerNumber]; LayerStats *myLss = &layerStats[layerNumber];
// valid state and layer number ? // valid state and layer number ?
if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) {
{
PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in saveKnotValueInDatabase()!"); PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in saveKnotValueInDatabase()!");
return; return;
} }
// is layer already completed ? // is layer already completed ?
if (myLss->layerIsCompletedAndInFile) if (myLss->layerIsCompletedAndInFile) {
{
PRINT(0, this, "ERROR: layer already completed and in file! function: saveKnotValueInDatabase()!"); PRINT(0, this, "ERROR: layer already completed and in file! function: saveKnotValueInDatabase()!");
return; return;
} }
// is layer already loaded? // is layer already loaded?
if (!myLss->layerIsLoaded) if (!myLss->layerIsLoaded) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
if (!myLss->layerIsLoaded) if (!myLss->layerIsLoaded) {
{
// reserve memory for this layer & create array for ply info with default value // reserve memory for this layer & create array for ply info with default value
myLss->shortKnotValueByte = new TwoBit[myLss->sizeInBytes]; myLss->shortKnotValueByte = new TwoBit[myLss->sizeInBytes];
memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes);
@ -681,8 +614,7 @@ void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int sta
// measure io-operations per second // measure io-operations per second
LARGE_INTEGER curTimeBefore; LARGE_INTEGER curTimeBefore;
if (MEASURE_IOPS && MEASURE_ONLY_IO) if (MEASURE_IOPS && MEASURE_ONLY_IO) {
{
QueryPerformanceCounter(&curTimeBefore); QueryPerformanceCounter(&curTimeBefore);
} }
@ -692,8 +624,7 @@ void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int sta
long mask = 0x00000003 << numBitsToShift; long mask = 0x00000003 << numBitsToShift;
long curShortKnotValueLong, newShortKnotValueLong; long curShortKnotValueLong, newShortKnotValueLong;
do do {
{
curShortKnotValueLong = *pShortKnotValue; curShortKnotValueLong = *pShortKnotValue;
newShortKnotValueLong = (curShortKnotValueLong & (~mask)) + (knotValue << numBitsToShift); newShortKnotValueLong = (curShortKnotValueLong & (~mask)) + (knotValue << numBitsToShift);
} while (InterlockedCompareExchange(pShortKnotValue, newShortKnotValueLong, curShortKnotValueLong) != curShortKnotValueLong); } while (InterlockedCompareExchange(pShortKnotValue, newShortKnotValueLong, curShortKnotValueLong) != curShortKnotValueLong);
@ -715,30 +646,25 @@ void MiniMax::savePlyInfoInDatabase(unsigned int layerNumber, unsigned int state
PlyInfo *myPis = &plyInfos[layerNumber]; PlyInfo *myPis = &plyInfos[layerNumber];
// valid state and layer number ? // valid state and layer number ?
if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) {
{
PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in savePlyInfoInDatabase()!"); PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in savePlyInfoInDatabase()!");
return; return;
} }
// is layer already completed ? // is layer already completed ?
if (myPis->plyInfoIsCompletedAndInFile) if (myPis->plyInfoIsCompletedAndInFile) {
{
PRINT(0, this, "ERROR: layer already completed and in file! function: savePlyInfoInDatabase()!"); PRINT(0, this, "ERROR: layer already completed and in file! function: savePlyInfoInDatabase()!");
return; return;
} }
// is layer already loaded // is layer already loaded
if (!myPis->plyInfoIsLoaded) if (!myPis->plyInfoIsLoaded) {
{
EnterCriticalSection(&csDatabase); EnterCriticalSection(&csDatabase);
if (!myPis->plyInfoIsLoaded) if (!myPis->plyInfoIsLoaded) {
{
// reserve memory for this layer & create array for ply info with default value // reserve memory for this layer & create array for ply info with default value
myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer];
for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) {
{
myPis->plyInfo[curKnot] = defValue; myPis->plyInfo[curKnot] = defValue;
} }
bytesAllocated = myPis->sizeInBytes; bytesAllocated = myPis->sizeInBytes;
@ -752,8 +678,7 @@ void MiniMax::savePlyInfoInDatabase(unsigned int layerNumber, unsigned int state
// measure io-operations per second // measure io-operations per second
LARGE_INTEGER curTimeBefore; LARGE_INTEGER curTimeBefore;
if (MEASURE_IOPS && MEASURE_ONLY_IO) if (MEASURE_IOPS && MEASURE_ONLY_IO) {
{
QueryPerformanceCounter(&curTimeBefore); QueryPerformanceCounter(&curTimeBefore);
} }

View File

@ -30,8 +30,7 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
// init retro vars // init retro vars
retroVars.thread.resize(threadManager.getNumThreads()); retroVars.thread.resize(threadManager.getNumThreads());
for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) {
{
retroVars.thread[threadNo].statesToProcess.resize(PLYINFO_EXP_VALUE, nullptr); retroVars.thread[threadNo].statesToProcess.resize(PLYINFO_EXP_VALUE, nullptr);
retroVars.thread[threadNo].numStatesToProcess = 0; retroVars.thread[threadNo].numStatesToProcess = 0;
retroVars.thread[threadNo].threadNo = threadNo; retroVars.thread[threadNo].threadNo = threadNo;
@ -40,13 +39,11 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
retroVars.layerInitialized.resize(skvfHeader.numLayers, false); retroVars.layerInitialized.resize(skvfHeader.numLayers, false);
retroVars.layersToCalculate = layersToCalculate; retroVars.layersToCalculate = layersToCalculate;
retroVars.pMiniMax = this; retroVars.pMiniMax = this;
for (retroVars.totalNumKnots = 0, retroVars.numKnotsToCalc = 0, curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) for (retroVars.totalNumKnots = 0, retroVars.numKnotsToCalc = 0, curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) {
{
retroVars.numKnotsToCalc += layerStats[layersToCalculate[curLayer]].knotsInLayer; retroVars.numKnotsToCalc += layerStats[layersToCalculate[curLayer]].knotsInLayer;
retroVars.totalNumKnots += layerStats[layersToCalculate[curLayer]].knotsInLayer; retroVars.totalNumKnots += layerStats[layersToCalculate[curLayer]].knotsInLayer;
retroVars.layerInitialized[layersToCalculate[curLayer]] = true; retroVars.layerInitialized[layersToCalculate[curLayer]] = true;
for (curSubLayer = 0; curSubLayer < layerStats[layersToCalculate[curLayer]].numSuccLayers; curSubLayer++) for (curSubLayer = 0; curSubLayer < layerStats[layersToCalculate[curLayer]].numSuccLayers; curSubLayer++) {
{
if (retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]]) if (retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]])
continue; continue;
else else
@ -63,16 +60,14 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
// initialization // initialization
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!initRetroAnalysis(retroVars)) if (!initRetroAnalysis(retroVars)) {
{
abortCalculation = true; abortCalculation = true;
goto freeMem; goto freeMem;
} }
// prepare count arrays // prepare count arrays
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!prepareCountArrays(retroVars)) if (!prepareCountArrays(retroVars)) {
{
abortCalculation = true; abortCalculation = true;
goto freeMem; goto freeMem;
} }
@ -83,33 +78,27 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
// iteration // iteration
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!performRetroAnalysis(retroVars)) if (!performRetroAnalysis(retroVars)) {
{
abortCalculation = true; abortCalculation = true;
goto freeMem; goto freeMem;
} }
// show output // show output
PRINT(2, this, " Bytes in memory: " << memoryUsed2); PRINT(2, this, " Bytes in memory: " << memoryUsed2);
for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) {
{
showLayerStats(layersToCalculate[curLayer]); showLayerStats(layersToCalculate[curLayer]);
} }
PRINT(2, this, ""); PRINT(2, this, "");
// free memory // free memory
freeMem: freeMem:
for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) {
{ for (plyCounter = 0; plyCounter < retroVars.thread[threadNo].statesToProcess.size(); plyCounter++) {
for (plyCounter = 0; plyCounter < retroVars.thread[threadNo].statesToProcess.size(); plyCounter++)
{
SAFE_DELETE(retroVars.thread[threadNo].statesToProcess[plyCounter]); SAFE_DELETE(retroVars.thread[threadNo].statesToProcess[plyCounter]);
} }
} }
for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) {
{ if (retroVars.countArrays[curLayer] != nullptr) {
if (retroVars.countArrays[curLayer] != nullptr)
{
memoryUsed2 -= layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType); memoryUsed2 -= layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType);
arrayInfos.removeArray(layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType), 0); arrayInfos.removeArray(layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType), 0);
} }
@ -135,8 +124,7 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars)
bool initAlreadyDone = false; // true if the initialization information is already available in a file bool initAlreadyDone = false; // true if the initialization information is already available in a file
// process each layer // process each layer
for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) {
{
// set current processed layer number // set current processed layer number
layerNumber = retroVars.layersToCalculate[curLayerId]; layerNumber = retroVars.layersToCalculate[curLayerId];
@ -152,8 +140,7 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars)
// does initialization file exist ? // does initialization file exist ?
CreateDirectoryA(ssInitArrayPath.str().c_str(), nullptr); CreateDirectoryA(ssInitArrayPath.str().c_str(), nullptr);
initArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInitArrayFilePath.str().c_str()); initArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInitArrayFilePath.str().c_str());
if (initArray->getFileSize() == (LONGLONG)layerStats[layerNumber].knotsInLayer) if (initArray->getFileSize() == (LONGLONG)layerStats[layerNumber].knotsInLayer) {
{
PRINT(2, this, " Loading init states from file: " << ssInitArrayFilePath.str()); PRINT(2, this, " Loading init states from file: " << ssInitArrayFilePath.str());
initAlreadyDone = true; initAlreadyDone = true;
} }
@ -173,8 +160,7 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars)
ThreadManager::ThreadVarsArray<InitRetroAnalysisVars> tva(threadManager.getNumThreads(), InitRetroAnalysisVars(this, &retroVars, layerNumber, initArray, initAlreadyDone)); ThreadManager::ThreadVarsArray<InitRetroAnalysisVars> tva(threadManager.getNumThreads(), InitRetroAnalysisVars(this, &retroVars, layerNumber, initArray, initAlreadyDone));
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeParallelLoop(initRetroAnalysisThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) switch (threadManager.executeParallelLoop(initRetroAnalysisThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -225,48 +211,38 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index)
iraVars->statesProcessed++; iraVars->statesProcessed++;
// print status // print status
if (iraVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (iraVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states");
} }
// layer initialization already done ? if so, then read from file // layer initialization already done ? if so, then read from file
if (iraVars->initAlreadyDone) if (iraVars->initAlreadyDone) {
{ if (!iraVars->bufferedFile->readBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) {
if (!iraVars->bufferedFile->readBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue))
{
PRINT(0, m, "ERROR: initArray->takeBytes() failed"); PRINT(0, m, "ERROR: initArray->takeBytes() failed");
return m->falseOrStop(); return m->falseOrStop();
} }
// initialization not done // initialization not done
} } else {
else
{
// set current selected situation // set current selected situation
if (!m->setSituation(iraVars->curThreadNo, curState.layerNumber, curState.stateNumber)) if (!m->setSituation(iraVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
{
curStateValue = SKV_VALUE_INVALID; curStateValue = SKV_VALUE_INVALID;
} } else {
else
{
// get value of current situation // get value of current situation
m->getValueOfSituation(iraVars->curThreadNo, floatValue, curStateValue); m->getValueOfSituation(iraVars->curThreadNo, floatValue, curStateValue);
} }
} }
// save init value // save init value
if (curStateValue != SKV_VALUE_INVALID) if (curStateValue != SKV_VALUE_INVALID) {
{
// save short knot value // save short knot value
m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue); m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue);
// put in list if state is final // put in list if state is final
if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) {
{
// ply info // ply info
m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, 0); m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, 0);
@ -277,11 +253,9 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index)
} }
// write data to file // write data to file
if (!iraVars->initAlreadyDone) if (!iraVars->initAlreadyDone) {
{
// curStateValue sollte 2 sein bei index == 1329322 // curStateValue sollte 2 sein bei index == 1329322
if (!iraVars->bufferedFile->writeBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) if (!iraVars->bufferedFile->writeBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) {
{
PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!");
return m->falseOrStop(); return m->falseOrStop();
} }
@ -320,15 +294,13 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
// prepare count arrays // prepare count arrays
CreateDirectoryA(ssCountArrayPath.str().c_str(), nullptr); CreateDirectoryA(ssCountArrayPath.str().c_str(), nullptr);
if ((hFileCountArray = CreateFileA(ssCountArrayFilePath.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)) == INVALID_HANDLE_VALUE) if ((hFileCountArray = CreateFileA(ssCountArrayFilePath.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)) == INVALID_HANDLE_VALUE) {
{
PRINT(0, this, "ERROR: Could not open File " << ssCountArrayFilePath.str() << "!"); PRINT(0, this, "ERROR: Could not open File " << ssCountArrayFilePath.str() << "!");
return falseOrStop(); return falseOrStop();
} }
// allocate memory for count arrays // allocate memory for count arrays
for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) {
{
numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer;
retroVars.countArrays[curLayer] = new CountArrayVarType[numKnotsInCurLayer]; retroVars.countArrays[curLayer] = new CountArrayVarType[numKnotsInCurLayer];
memoryUsed2 += numKnotsInCurLayer * sizeof(CountArrayVarType); memoryUsed2 += numKnotsInCurLayer * sizeof(CountArrayVarType);
@ -336,12 +308,10 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
} }
// load file if already existend // load file if already existend
if (GetFileSizeEx(hFileCountArray, &fileSize) && fileSize.QuadPart == retroVars.numKnotsToCalc) if (GetFileSizeEx(hFileCountArray, &fileSize) && fileSize.QuadPart == retroVars.numKnotsToCalc) {
{
PRINT(2, this, " Load number of succedors from file: " << ssCountArrayFilePath.str().c_str()); PRINT(2, this, " Load number of succedors from file: " << ssCountArrayFilePath.str().c_str());
for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) {
{
numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer;
if (!ReadFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwRead, nullptr)) if (!ReadFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwRead, nullptr))
return falseOrStop(); return falseOrStop();
@ -350,30 +320,24 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
} }
// else calculate number of succedding states // else calculate number of succedding states
} } else {
else
{
// Set default value 0 // Set default value 0
for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) {
{
numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer;
for (curState.stateNumber = 0; curState.stateNumber < numKnotsInCurLayer; curState.stateNumber++) for (curState.stateNumber = 0; curState.stateNumber < numKnotsInCurLayer; curState.stateNumber++) {
{
retroVars.countArrays[curLayer][curState.stateNumber] = defValue; retroVars.countArrays[curLayer][curState.stateNumber] = defValue;
} }
} }
// calc values // calc values
if (!calcNumSuccedors(retroVars)) if (!calcNumSuccedors(retroVars)) {
{
CloseHandle(hFileCountArray); CloseHandle(hFileCountArray);
return false; return false;
} }
// save to file // save to file
for (curLayer = 0, dwWritten = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) for (curLayer = 0, dwWritten = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) {
{
numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer;
if (!WriteFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwWritten, nullptr)) if (!WriteFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwWritten, nullptr))
return falseOrStop(); return falseOrStop();
@ -402,16 +366,14 @@ bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars)
vector<bool> succCalculated(skvfHeader.numLayers, false); // vector<bool> succCalculated(skvfHeader.numLayers, false); //
// process each layer // process each layer
for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) {
{
// set current processed layer number // set current processed layer number
layerNumber = retroVars.layersToCalculate[curLayerId]; layerNumber = retroVars.layersToCalculate[curLayerId];
PRINT(0, this, " *** Calculate number of succeding states for each state of layer " << layerNumber << " ***"); PRINT(0, this, " *** Calculate number of succeding states for each state of layer " << layerNumber << " ***");
// process layer ... // process layer ...
if (!succCalculated[layerNumber]) if (!succCalculated[layerNumber]) {
{
// prepare parameters for multithreading // prepare parameters for multithreading
succCalculated[layerNumber] = true; succCalculated[layerNumber] = true;
@ -419,8 +381,7 @@ bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars)
ThreadManager::ThreadVarsArray<AddNumSuccedorsVars> tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, layerNumber)); ThreadManager::ThreadVarsArray<AddNumSuccedorsVars> tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, layerNumber));
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -438,15 +399,12 @@ bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars)
return falseOrStop(); return falseOrStop();
// don't calc layers twice // don't calc layers twice
} } else {
else
{
return falseOrStop(); return falseOrStop();
} }
// ... and process succeding layers // ... and process succeding layers
for (curState.layerNumber = 0; curState.layerNumber < layerStats[layerNumber].numSuccLayers; curState.layerNumber++) for (curState.layerNumber = 0; curState.layerNumber < layerStats[layerNumber].numSuccLayers; curState.layerNumber++) {
{
// get current pred. layer // get current pred. layer
succState.layerNumber = layerStats[layerNumber].succLayers[curState.layerNumber]; succState.layerNumber = layerStats[layerNumber].succLayers[curState.layerNumber];
@ -469,8 +427,7 @@ bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars)
ThreadManager::ThreadVarsArray<AddNumSuccedorsVars> tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, succState.layerNumber)); ThreadManager::ThreadVarsArray<AddNumSuccedorsVars> tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, succState.layerNumber));
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[succState.layerNumber].knotsInLayer - 1, 1)) switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[succState.layerNumber].knotsInLayer - 1, 1)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -518,8 +475,7 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
// print status // print status
ansVars->statesProcessed++; ansVars->statesProcessed++;
if (ansVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (ansVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(2, m, " Already processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); PRINT(2, m, " Already processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states");
} }
@ -530,8 +486,7 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
return TM_RETURN_VALUE_OK; return TM_RETURN_VALUE_OK;
// set current selected situation // set current selected situation
if (!m->setSituation(ansVars->curThreadNo, curState.layerNumber, curState.stateNumber)) if (!m->setSituation(ansVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
{
PRINT(0, m, "ERROR: setSituation() returned false!"); PRINT(0, m, "ERROR: setSituation() returned false!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
@ -540,16 +495,14 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
m->getPredecessors(ansVars->curThreadNo, &amountOfPred, ansVars->predVars); m->getPredecessors(ansVars->curThreadNo, &amountOfPred, ansVars->predVars);
// iteration // iteration
for (curPred = 0; curPred < amountOfPred; curPred++) for (curPred = 0; curPred < amountOfPred; curPred++) {
{
// current predecessor // current predecessor
predState.layerNumber = ansVars->predVars[curPred].predLayerNumbers; predState.layerNumber = ansVars->predVars[curPred].predLayerNumbers;
predState.stateNumber = ansVars->predVars[curPred].predStateNumbers; predState.stateNumber = ansVars->predVars[curPred].predStateNumbers;
// don't calculate states from layers above yet // don't calculate states from layers above yet
for (curLayerId = 0; curLayerId < numLayersToCalculate; curLayerId++) for (curLayerId = 0; curLayerId < numLayersToCalculate; curLayerId++) {
{
if (ansVars->retroVars->layersToCalculate[curLayerId] == predState.layerNumber) if (ansVars->retroVars->layersToCalculate[curLayerId] == predState.layerNumber)
break; break;
} }
@ -557,8 +510,7 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
continue; continue;
// put in list (with states to be processed) if state is final // put in list (with states to be processed) if state is final
if (!cuStateAddedToProcessQueue && (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST)) if (!cuStateAddedToProcessQueue && (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST)) {
{
m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPlies); m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPlies);
m->addStateToProcessQueue(*ansVars->retroVars, ansVars->retroVars->thread[ansVars->curThreadNo], numPlies, &curState); m->addStateToProcessQueue(*ansVars->retroVars, ansVars->retroVars->thread[ansVars->curThreadNo], numPlies, &curState);
cuStateAddedToProcessQueue = true; cuStateAddedToProcessQueue = true;
@ -570,17 +522,13 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
long mask = 0x000000ff << numBitsToShift; long mask = 0x000000ff << numBitsToShift;
long curCountLong, newCountLong; long curCountLong, newCountLong;
do do {
{
curCountLong = *pCountValue; curCountLong = *pCountValue;
countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift);
if (countValue == 255) if (countValue == 255) {
{
PRINT(0, m, "ERROR: maximum value for Count[] reached!"); PRINT(0, m, "ERROR: maximum value for Count[] reached!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} } else {
else
{
countValue++; countValue++;
newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift);
} }
@ -607,8 +555,7 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars)
curCalculationActionId = MM_ACTION_PERFORM_RETRO_ANAL; curCalculationActionId = MM_ACTION_PERFORM_RETRO_ANAL;
// process each state in the current layer // process each state in the current layer
switch (threadManager.executeInParallel(performRetroAnalysisThreadProc, (void **)&retroVars, 0)) switch (threadManager.executeInParallel(performRetroAnalysisThreadProc, (void **)&retroVars, 0)) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
@ -621,10 +568,8 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars)
} }
// if there are still states to process, than something went wrong // if there are still states to process, than something went wrong
for (unsigned int curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) for (unsigned int curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) {
{ if (retroVars.thread[curThreadNo].numStatesToProcess) {
if (retroVars.thread[curThreadNo].numStatesToProcess)
{
PRINT(0, this, "ERROR: There are still states to process after performing retro analysis!"); PRINT(0, this, "ERROR: There are still states to process after performing retro analysis!");
return falseOrStop(); return falseOrStop();
} }
@ -632,10 +577,8 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars)
// copy drawn and invalid states to ply info // copy drawn and invalid states to ply info
PRINT(2, this, " Copy drawn and invalid states to ply info database..."); PRINT(2, this, " Copy drawn and invalid states to ply info database...");
for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) {
{ for (curState.layerNumber = retroVars.layersToCalculate[curLayerId], curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) {
for (curState.layerNumber = retroVars.layersToCalculate[curLayerId], curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++)
{
readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue);
if (curStateValue == SKV_VALUE_GAME_DRAWN) if (curStateValue == SKV_VALUE_GAME_DRAWN)
savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_DRAWN); savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_DRAWN);
@ -677,28 +620,22 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
TwoBit curStateValue; // current state value TwoBit curStateValue; // current state value
RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS];
for (numStatesProcessed = 0, curNumPlies = 0; curNumPlies < threadVars->statesToProcess.size(); curNumPlies++) for (numStatesProcessed = 0, curNumPlies = 0; curNumPlies < threadVars->statesToProcess.size(); curNumPlies++) {
{
// skip empty and uninitialized cyclic arrays // skip empty and uninitialized cyclic arrays
if (threadVars->statesToProcess[curNumPlies] != nullptr) if (threadVars->statesToProcess[curNumPlies] != nullptr) {
{
if (threadNo == 0) if (threadNo == 0) {
{
PRINT(0, m, " Current number of plies: " << (unsigned int)curNumPlies << "/" << threadVars->statesToProcess.size()); PRINT(0, m, " Current number of plies: " << (unsigned int)curNumPlies << "/" << threadVars->statesToProcess.size());
for (threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) for (threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) {
{
PRINT(0, m, " States to process for thread " << threadCounter << ": " << retroVars->thread[threadCounter].numStatesToProcess); PRINT(0, m, " States to process for thread " << threadCounter << ": " << retroVars->thread[threadCounter].numStatesToProcess);
} }
} }
while (threadVars->statesToProcess[curNumPlies]->takeBytes(sizeof(StateAdress), (unsigned char *)&curState)) while (threadVars->statesToProcess[curNumPlies]->takeBytes(sizeof(StateAdress), (unsigned char *)&curState)) {
{
// execution cancelled by user? // execution cancelled by user?
if (m->threadManager.wasExecutionCancelled()) if (m->threadManager.wasExecutionCancelled()) {
{
PRINT(0, m, "\n****************************************\nSub-thread no. " << threadNo << ": Execution cancelled by user!\n****************************************\n"); PRINT(0, m, "\n****************************************\nSub-thread no. " << threadNo << ": Execution cancelled by user!\n****************************************\n");
return TM_RETURN_VALUE_EXECUTION_CANCELLED; return TM_RETURN_VALUE_EXECUTION_CANCELLED;
} }
@ -707,8 +644,7 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue);
m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPliesTillCurState); m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPliesTillCurState);
if (numPliesTillCurState != curNumPlies) if (numPliesTillCurState != curNumPlies) {
{
PRINT(0, m, "ERROR: numPliesTillCurState != curNumPlies"); PRINT(0, m, "ERROR: numPliesTillCurState != curNumPlies");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
@ -716,19 +652,16 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
// console output // console output
numStatesProcessed++; numStatesProcessed++;
threadVars->numStatesToProcess--; threadVars->numStatesToProcess--;
if (numStatesProcessed % OUTPUT_EVERY_N_STATES == 0) if (numStatesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
for (totalNumStatesToProcess = 0, threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) for (totalNumStatesToProcess = 0, threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) {
{
totalNumStatesToProcess += retroVars->thread[threadCounter].numStatesToProcess; totalNumStatesToProcess += retroVars->thread[threadCounter].numStatesToProcess;
} }
PRINT(2, m, " states already processed: " << m->numStatesProcessed << " \t states still in list: " << totalNumStatesToProcess); PRINT(2, m, " states already processed: " << m->numStatesProcessed << " \t states still in list: " << totalNumStatesToProcess);
} }
// set current selected situation // set current selected situation
if (!m->setSituation(threadNo, curState.layerNumber, curState.stateNumber)) if (!m->setSituation(threadNo, curState.layerNumber, curState.stateNumber)) {
{
PRINT(0, m, "ERROR: setSituation() returned false!"); PRINT(0, m, "ERROR: setSituation() returned false!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
@ -737,16 +670,14 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
m->getPredecessors(threadNo, &amountOfPred, predVars); m->getPredecessors(threadNo, &amountOfPred, predVars);
// iteration // iteration
for (curPred = 0; curPred < amountOfPred; curPred++) for (curPred = 0; curPred < amountOfPred; curPred++) {
{
// current predecessor // current predecessor
predState.layerNumber = predVars[curPred].predLayerNumbers; predState.layerNumber = predVars[curPred].predLayerNumbers;
predState.stateNumber = predVars[curPred].predStateNumbers; predState.stateNumber = predVars[curPred].predStateNumbers;
// don't calculate states from layers above yet // don't calculate states from layers above yet
for (curLayerId = 0; curLayerId < retroVars->layersToCalculate.size(); curLayerId++) for (curLayerId = 0; curLayerId < retroVars->layersToCalculate.size(); curLayerId++) {
{
if (retroVars->layersToCalculate[curLayerId] == predState.layerNumber) if (retroVars->layersToCalculate[curLayerId] == predState.layerNumber)
break; break;
} }
@ -757,41 +688,32 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
m->readKnotValueFromDatabase(predState.layerNumber, predState.stateNumber, predStateValue); m->readKnotValueFromDatabase(predState.layerNumber, predState.stateNumber, predStateValue);
// only drawn states are relevant here, since the other are already calculated // only drawn states are relevant here, since the other are already calculated
if (predStateValue == SKV_VALUE_GAME_DRAWN) if (predStateValue == SKV_VALUE_GAME_DRAWN) {
{
// if current considered state is a lost game then all predecessors are a won game // if current considered state is a lost game then all predecessors are a won game
if (curStateValue == m->skvPerspectiveMatrix[SKV_VALUE_GAME_LOST][predVars[curPred].playerToMoveChanged ? PL_TO_MOVE_CHANGED : PL_TO_MOVE_UNCHANGED]) if (curStateValue == m->skvPerspectiveMatrix[SKV_VALUE_GAME_LOST][predVars[curPred].playerToMoveChanged ? PL_TO_MOVE_CHANGED : PL_TO_MOVE_UNCHANGED]) {
{
m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_WON); m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_WON);
m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); // (requirement: curNumPlies == numPliesTillCurState) m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); // (requirement: curNumPlies == numPliesTillCurState)
if (numPliesTillCurState + 1 < curNumPlies) if (numPliesTillCurState + 1 < curNumPlies) {
{
PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
m->addStateToProcessQueue(*retroVars, *threadVars, numPliesTillCurState + 1, &predState); m->addStateToProcessQueue(*retroVars, *threadVars, numPliesTillCurState + 1, &predState);
// if current state is a won game, then this state is not an option any more for all predecessors // if current state is a won game, then this state is not an option any more for all predecessors
} } else {
else
{
// reduce count value by one // reduce count value by one
long *pCountValue = ((long *)retroVars->countArrays[curLayerId]) + predState.stateNumber / (sizeof(long) / sizeof(CountArrayVarType)); long *pCountValue = ((long *)retroVars->countArrays[curLayerId]) + predState.stateNumber / (sizeof(long) / sizeof(CountArrayVarType));
long numBitsToShift = sizeof(CountArrayVarType) * 8 * (predState.stateNumber % (sizeof(long) / sizeof(CountArrayVarType))); // little-endian byte-order long numBitsToShift = sizeof(CountArrayVarType) * 8 * (predState.stateNumber % (sizeof(long) / sizeof(CountArrayVarType))); // little-endian byte-order
long mask = 0x000000ff << numBitsToShift; long mask = 0x000000ff << numBitsToShift;
long curCountLong, newCountLong; long curCountLong, newCountLong;
do do {
{
curCountLong = *pCountValue; curCountLong = *pCountValue;
countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift);
if (countValue > 0) if (countValue > 0) {
{
countValue--; countValue--;
newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift);
} } else {
else
{
PRINT(0, m, "ERROR: Count is already zero!"); PRINT(0, m, "ERROR: Count is already zero!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
@ -799,17 +721,14 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
// ply info (requirement: curNumPlies == numPliesTillCurState) // ply info (requirement: curNumPlies == numPliesTillCurState)
m->readPlyInfoFromDatabase(predState.layerNumber, predState.stateNumber, numPliesTillPredState); m->readPlyInfoFromDatabase(predState.layerNumber, predState.stateNumber, numPliesTillPredState);
if (numPliesTillPredState == PLYINFO_VALUE_UNCALCULATED || numPliesTillCurState + 1 > numPliesTillPredState) if (numPliesTillPredState == PLYINFO_VALUE_UNCALCULATED || numPliesTillCurState + 1 > numPliesTillPredState) {
{
m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1);
} }
// when all successor are won states then this is a lost state (this should only be the case for one thread) // when all successor are won states then this is a lost state (this should only be the case for one thread)
if (countValue == 0) if (countValue == 0) {
{
m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_LOST); m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_LOST);
if (numPliesTillCurState + 1 < curNumPlies) if (numPliesTillCurState + 1 < curNumPlies) {
{
PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!");
return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; return TM_RETURN_VALUE_TERMINATE_ALL_THREADS;
} }
@ -836,15 +755,13 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
bool MiniMax::addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState) bool MiniMax::addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState)
{ {
// resize vector if too small // resize vector if too small
if (plyNumber >= threadVars.statesToProcess.size()) if (plyNumber >= threadVars.statesToProcess.size()) {
{
threadVars.statesToProcess.resize(max(plyNumber + 1, 10 * threadVars.statesToProcess.size()), nullptr); threadVars.statesToProcess.resize(max(plyNumber + 1, 10 * threadVars.statesToProcess.size()), nullptr);
PRINT(4, this, " statesToProcess resized to " << threadVars.statesToProcess.size()); PRINT(4, this, " statesToProcess resized to " << threadVars.statesToProcess.size());
} }
// initialize cyclic array if necessary // initialize cyclic array if necessary
if (threadVars.statesToProcess[plyNumber] == nullptr) if (threadVars.statesToProcess[plyNumber] == nullptr) {
{
stringstream ssStatesToProcessFilePath; stringstream ssStatesToProcessFilePath;
stringstream ssStatesToProcessPath; stringstream ssStatesToProcessPath;
ssStatesToProcessPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "statesToProcess"; ssStatesToProcessPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "statesToProcess";
@ -856,8 +773,7 @@ bool MiniMax::addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAn
} }
// add state // add state
if (!threadVars.statesToProcess[plyNumber]->addBytes(sizeof(StateAdress), (unsigned char *)pState)) if (!threadVars.statesToProcess[plyNumber]->addBytes(sizeof(StateAdress), (unsigned char *)pState)) {
{
PRINT(0, this, "ERROR: Cyclic list to small! numStatesToProcess:" << threadVars.numStatesToProcess); PRINT(0, this, "ERROR: Cyclic list to small! numStatesToProcess:" << threadVars.numStatesToProcess);
return falseOrStop(); return falseOrStop();
} }

View File

@ -19,8 +19,7 @@ bool MiniMax::testLayer(unsigned int layerNumber)
unsigned int returnValue; unsigned int returnValue;
// database open? // database open?
if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) {
{
PRINT(0, this, "ERROR: Database file not open!"); PRINT(0, this, "ERROR: Database file not open!");
return falseOrStop(); return falseOrStop();
} }
@ -36,8 +35,7 @@ bool MiniMax::testLayer(unsigned int layerNumber)
curCalculatedLayer = layerNumber; curCalculatedLayer = layerNumber;
curCalculationActionId = MM_ACTION_TESTING_LAYER; curCalculationActionId = MM_ACTION_TESTING_LAYER;
TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()];
for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) {
{
tlVars[curThreadNo].curThreadNo = curThreadNo; tlVars[curThreadNo].curThreadNo = curThreadNo;
tlVars[curThreadNo].pMiniMax = this; tlVars[curThreadNo].pMiniMax = this;
tlVars[curThreadNo].layerNumber = layerNumber; tlVars[curThreadNo].layerNumber = layerNumber;
@ -49,26 +47,21 @@ bool MiniMax::testLayer(unsigned int layerNumber)
// process each state in the current layer // process each state in the current layer
returnValue = threadManager.executeParallelLoop(testLayerThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); returnValue = threadManager.executeParallelLoop(testLayerThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1);
switch (returnValue) switch (returnValue) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
// reduce and delete thread specific data // reduce and delete thread specific data
for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) {
{
numStatesProcessed += tlVars[curThreadNo].statesProcessed; numStatesProcessed += tlVars[curThreadNo].statesProcessed;
SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase);
SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged);
SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos);
} }
SAFE_DELETE_ARRAY(tlVars); SAFE_DELETE_ARRAY(tlVars);
if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) {
{
PRINT(0, this, "Main thread: Execution cancelled by user"); PRINT(0, this, "Main thread: Execution cancelled by user");
return false; // ... better would be to return a cancel-specific value return false; // ... better would be to return a cancel-specific value
} } else {
else
{
break; break;
} }
default: default:
@ -78,14 +71,11 @@ bool MiniMax::testLayer(unsigned int layerNumber)
} }
// layer is not ok // layer is not ok
if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) {
{
PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber);
return falseOrStop(); return falseOrStop();
// layer is ok // layer is ok
} } else {
else
{
PRINT(1, this, " TEST PASSED !" << endl PRINT(1, this, " TEST PASSED !" << endl
<< endl); << endl);
return true; return true;
@ -124,8 +114,7 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
// output // output
tlVars->statesProcessed++; tlVars->statesProcessed++;
if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[layerNumber].knotsInLayer << " tested"); PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[layerNumber].knotsInLayer << " tested");
} }
@ -135,24 +124,19 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
m->readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); m->readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState);
// prepare the situation // prepare the situation
if (!m->setSituation(threadNo, layerNumber, stateNumber)) if (!m->setSituation(threadNo, layerNumber, stateNumber)) {
{
// when situation cannot be constructed then state must be marked as invalid in database // when situation cannot be constructed then state must be marked as invalid in database
if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID) if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID) {
{
PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Could not set situation, but value is not invalid."); PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Could not set situation, but value is not invalid.");
goto errorInDatabase; goto errorInDatabase;
} } else {
else
{
return TM_RETURN_VALUE_OK; return TM_RETURN_VALUE_OK;
} }
} }
// debug information // debug information
if (m->verbosity > 5) if (m->verbosity > 5) {
{
PRINT(5, m, "layer: " << layerNumber << " state: " << stateNumber); PRINT(5, m, "layer: " << layerNumber << " state: " << stateNumber);
m->printBoard(threadNo, shortValueInDatabase); m->printBoard(threadNo, shortValueInDatabase);
} }
@ -162,30 +146,24 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
idPossibility = m->getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); idPossibility = m->getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities);
// unable to move // unable to move
if (numPossibilities == 0) if (numPossibilities == 0) {
{
// get ingame value // get ingame value
m->getValueOfSituation(threadNo, floatValueInGame, shortValueInGame); m->getValueOfSituation(threadNo, floatValueInGame, shortValueInGame);
// compare database with game // compare database with game
if (shortValueInDatabase != shortValueInGame || numPliesTillCurState != 0) if (shortValueInDatabase != shortValueInGame || numPliesTillCurState != 0) {
{
PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of possibilities is zero, but knot value is not invalid or ply info equal zero."); PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of possibilities is zero, but knot value is not invalid or ply info equal zero.");
goto errorInDatabase; goto errorInDatabase;
} }
if (shortValueInDatabase == SKV_VALUE_INVALID) if (shortValueInDatabase == SKV_VALUE_INVALID) {
{
PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of possibilities is zero, but knot value is invalid."); PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of possibilities is zero, but knot value is invalid.");
goto errorInDatabase; goto errorInDatabase;
} }
} } else {
else
{
// check each possible move // check each possible move
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{
// move // move
m->move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); m->move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities);
@ -196,15 +174,13 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
hasCurPlayerChanged[i] = (m->getOpponentLevel(threadNo) == true); hasCurPlayerChanged[i] = (m->getOpponentLevel(threadNo) == true);
// debug information // debug information
if (m->verbosity > 5) if (m->verbosity > 5) {
{
PRINT(5, m, "layer: " << tmpLayerNumber << " state: " << tmpStateNumber << " value: " << (int)subValueInDatabase[i]); PRINT(5, m, "layer: " << tmpLayerNumber << " state: " << tmpStateNumber << " value: " << (int)subValueInDatabase[i]);
m->printBoard(threadNo, subValueInDatabase[i]); m->printBoard(threadNo, subValueInDatabase[i]);
} }
// if layer or state number is invalid then value of testes state must be invalid // if layer or state number is invalid then value of testes state must be invalid
if (invalidLayerOrStateNumber && shortValueInDatabase != SKV_VALUE_INVALID) if (invalidLayerOrStateNumber && shortValueInDatabase != SKV_VALUE_INVALID) {
{
PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Succeding state has invalid layer (" << tmpLayerNumber << ")or state number (" << tmpStateNumber << "), but tested state is not marked as invalid."); PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Succeding state has invalid layer (" << tmpLayerNumber << ")or state number (" << tmpStateNumber << "), but tested state is not marked as invalid.");
goto errorInDatabase; goto errorInDatabase;
} }
@ -216,50 +192,39 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
} }
// value possible? // value possible?
switch (shortValueInDatabase) switch (shortValueInDatabase) {
{
case SKV_VALUE_GAME_LOST: case SKV_VALUE_GAME_LOST:
// all possible moves must be lost for the current player or won for the opponent // all possible moves must be lost for the current player or won for the opponent
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{ if (subValueInDatabase[i] != ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST) && subValueInDatabase[i] != SKV_VALUE_INVALID) {
if (subValueInDatabase[i] != ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST) && subValueInDatabase[i] != SKV_VALUE_INVALID)
{
PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be lost for the current player or won for the opponent"); PRINT(0, m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be lost for the current player or won for the opponent");
goto errorInDatabase; goto errorInDatabase;
} }
} }
// not all options can be invalid // not all options can be invalid
for (j = 0, i = 0; i < numPossibilities; i++) for (j = 0, i = 0; i < numPossibilities; i++) {
{ if (subValueInDatabase[i] == SKV_VALUE_INVALID) {
if (subValueInDatabase[i] == SKV_VALUE_INVALID)
{
j++; j++;
} }
} }
if (j == numPossibilities) if (j == numPossibilities) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ". Not all options can be invalid"); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ". Not all options can be invalid");
} }
// ply info must be max(subPlyInfos[]+1) // ply info must be max(subPlyInfos[]+1)
max = 0; max = 0;
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{ if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST)) {
if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST)) if (subPlyInfos[i] + 1 > max) {
{
if (subPlyInfos[i] + 1 > max)
{
max = subPlyInfos[i] + 1; max = subPlyInfos[i] + 1;
} }
} }
} }
if (numPliesTillCurState > PLYINFO_VALUE_DRAWN) if (numPliesTillCurState > PLYINFO_VALUE_DRAWN) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is LOST, but numPliesTillCurState is bigger than PLYINFO_MAX_VALUE."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is LOST, but numPliesTillCurState is bigger than PLYINFO_MAX_VALUE.");
goto errorInDatabase; goto errorInDatabase;
} }
if (numPliesTillCurState != max) if (numPliesTillCurState != max) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not maximal for LOST state."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not maximal for LOST state.");
goto errorInDatabase; goto errorInDatabase;
} }
@ -268,37 +233,30 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
case SKV_VALUE_GAME_WON: case SKV_VALUE_GAME_WON:
// at least one possible move must be lost for the opponent or won for the current player // at least one possible move must be lost for the opponent or won for the current player
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{
// if (subValueInDatabase[i] == SKV_VALUE_INVALID) { PRINT(0,m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one possible move must be lost for the opponent or won for the current player. But subValueInDatabase[i] == SKV_VALUE_INVALID."); goto errorInDatabase; } // if (subValueInDatabase[i] == SKV_VALUE_INVALID) { PRINT(0,m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one possible move must be lost for the opponent or won for the current player. But subValueInDatabase[i] == SKV_VALUE_INVALID."); goto errorInDatabase; }
if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON))
i = numPossibilities; i = numPossibilities;
} }
if (i == numPossibilities) if (i == numPossibilities) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one possible move must be lost for the opponent or won for the current player."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one possible move must be lost for the opponent or won for the current player.");
goto errorInDatabase; goto errorInDatabase;
} }
// ply info must be min(subPlyInfos[]+1) // ply info must be min(subPlyInfos[]+1)
min = PLYINFO_VALUE_DRAWN; min = PLYINFO_VALUE_DRAWN;
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{ if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) {
if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) if (subPlyInfos[i] + 1 < min) {
{
if (subPlyInfos[i] + 1 < min)
{
min = subPlyInfos[i] + 1; min = subPlyInfos[i] + 1;
} }
} }
} }
if (numPliesTillCurState > PLYINFO_VALUE_DRAWN) if (numPliesTillCurState > PLYINFO_VALUE_DRAWN) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is WON, but numPliesTillCurState is bigger than PLYINFO_MAX_VALUE."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is WON, but numPliesTillCurState is bigger than PLYINFO_MAX_VALUE.");
goto errorInDatabase; goto errorInDatabase;
} }
if (numPliesTillCurState != min) if (numPliesTillCurState != min) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not minimal for WON state."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not minimal for WON state.");
goto errorInDatabase; goto errorInDatabase;
} }
@ -307,11 +265,9 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
case SKV_VALUE_GAME_DRAWN: case SKV_VALUE_GAME_DRAWN:
// all possible moves must be won for the opponent, lost for the current player or drawn // all possible moves must be won for the opponent, lost for the current player or drawn
for (j = 0, i = 0; i < numPossibilities; i++) for (j = 0, i = 0; i < numPossibilities; i++) {
{
// if (subValueInDatabase[i] == SKV_VALUE_INVALID) { PRINT(0,m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be won for the opponent, lost for the current player or drawn. But subValueInDatabase[i] == SKV_VALUE_INVALID."); goto errorInDatabase; } // if (subValueInDatabase[i] == SKV_VALUE_INVALID) { PRINT(0,m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be won for the opponent, lost for the current player or drawn. But subValueInDatabase[i] == SKV_VALUE_INVALID."); goto errorInDatabase; }
if (subValueInDatabase[i] != ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST) && subValueInDatabase[i] != SKV_VALUE_GAME_DRAWN && subValueInDatabase[i] != SKV_VALUE_INVALID) if (subValueInDatabase[i] != ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST) && subValueInDatabase[i] != SKV_VALUE_GAME_DRAWN && subValueInDatabase[i] != SKV_VALUE_INVALID) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be won for the opponent, lost for the current player or drawn."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": All possible moves must be won for the opponent, lost for the current player or drawn.");
goto errorInDatabase; goto errorInDatabase;
} }
@ -320,15 +276,13 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
} }
// at least one succeding state must be drawn // at least one succeding state must be drawn
if (j == 0) if (j == 0) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one succeding state must be drawn."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one succeding state must be drawn.");
goto errorInDatabase; goto errorInDatabase;
} }
// ply info must also be drawn // ply info must also be drawn
if (numPliesTillCurState != PLYINFO_VALUE_DRAWN) if (numPliesTillCurState != PLYINFO_VALUE_DRAWN) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is drawn but ply info is not!"); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is drawn but ply info is not!");
goto errorInDatabase; goto errorInDatabase;
} }
@ -336,19 +290,16 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
case SKV_VALUE_INVALID: case SKV_VALUE_INVALID:
// if setSituation() returned true but state value is invalid, then all following states must be invalid // if setSituation() returned true but state value is invalid, then all following states must be invalid
for (i = 0; i < numPossibilities; i++) for (i = 0; i < numPossibilities; i++) {
{
if (subValueInDatabase[i] != SKV_VALUE_INVALID) if (subValueInDatabase[i] != SKV_VALUE_INVALID)
break; break;
} }
if (i != numPossibilities) if (i != numPossibilities) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": If setSituation() returned true but state value is invalid, then all following states must be invalid."); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": If setSituation() returned true but state value is invalid, then all following states must be invalid.");
goto errorInDatabase; goto errorInDatabase;
} }
// ply info must also be invalid // ply info must also be invalid
if (numPliesTillCurState != PLYINFO_VALUE_INVALID) if (numPliesTillCurState != PLYINFO_VALUE_INVALID) {
{
PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is invalid but ply info is not!"); PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Knot value is invalid but ply info is not!");
goto errorInDatabase; goto errorInDatabase;
} }
@ -409,8 +360,7 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber)
numStatesProcessed = 0; numStatesProcessed = 0;
curCalculationActionId = MM_ACTION_TESTING_LAYER; curCalculationActionId = MM_ACTION_TESTING_LAYER;
TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()];
for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) {
{
tlVars[curThreadNo].curThreadNo = curThreadNo; tlVars[curThreadNo].curThreadNo = curThreadNo;
tlVars[curThreadNo].pMiniMax = this; tlVars[curThreadNo].pMiniMax = this;
tlVars[curThreadNo].layerNumber = layerNumber; tlVars[curThreadNo].layerNumber = layerNumber;
@ -422,26 +372,21 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber)
// process each state in the current layer // process each state in the current layer
returnValue = threadManager.executeParallelLoop(testSetSituationThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); returnValue = threadManager.executeParallelLoop(testSetSituationThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1);
switch (returnValue) switch (returnValue) {
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
case TM_RETURN_VALUE_EXECUTION_CANCELLED: case TM_RETURN_VALUE_EXECUTION_CANCELLED:
// reduce and delete thread specific data // reduce and delete thread specific data
for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) {
{
numStatesProcessed += tlVars[curThreadNo].statesProcessed; numStatesProcessed += tlVars[curThreadNo].statesProcessed;
SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase);
SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged);
SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos);
} }
SAFE_DELETE_ARRAY(tlVars); SAFE_DELETE_ARRAY(tlVars);
if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) {
{
PRINT(0, this, "Main thread: Execution cancelled by user"); PRINT(0, this, "Main thread: Execution cancelled by user");
return false; // ... better would be to return a cancel-specific value return false; // ... better would be to return a cancel-specific value
} } else {
else
{
break; break;
} }
default: default:
@ -451,14 +396,11 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber)
} }
// layer is not ok // layer is not ok
if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) {
{
PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber);
return falseOrStop(); return falseOrStop();
// layer is ok // layer is ok
} } else {
else
{
PRINT(1, this, " TEST PASSED !" << endl PRINT(1, this, " TEST PASSED !" << endl
<< endl); << endl);
return true; return true;
@ -488,19 +430,15 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index)
// output // output
tlVars->statesProcessed++; tlVars->statesProcessed++;
if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) {
{
m->numStatesProcessed += OUTPUT_EVERY_N_STATES; m->numStatesProcessed += OUTPUT_EVERY_N_STATES;
PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[curState.layerNumber].knotsInLayer << " tested"); PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[curState.layerNumber].knotsInLayer << " tested");
} }
// set state // set state
if (m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber)) if (m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
{
m->getValueOfSituation(tlVars->curThreadNo, floatValue, shortKnotValue); m->getValueOfSituation(tlVars->curThreadNo, floatValue, shortKnotValue);
} } else {
else
{
shortKnotValue = SKV_VALUE_INVALID; shortKnotValue = SKV_VALUE_INVALID;
} }
@ -508,26 +446,20 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index)
idPossibility = m->getPossibilities(tlVars->curThreadNo, &knot.numPossibilities, &knot.isOpponentLevel, &pPossibilities); idPossibility = m->getPossibilities(tlVars->curThreadNo, &knot.numPossibilities, &knot.isOpponentLevel, &pPossibilities);
// unable to move // unable to move
if (knot.numPossibilities == 0) if (knot.numPossibilities == 0) {
{ if (shortKnotValue == SKV_VALUE_GAME_DRAWN) {
if (shortKnotValue == SKV_VALUE_GAME_DRAWN)
{
PRINT(0, m, "ERROR: Layer " << curState.layerNumber << " and state " << curState.stateNumber << ". setSituation() returned true, although getPossibilities() yields no possible moves."); PRINT(0, m, "ERROR: Layer " << curState.layerNumber << " and state " << curState.stateNumber << ". setSituation() returned true, although getPossibilities() yields no possible moves.");
return m->falseOrStop(); return m->falseOrStop();
} }
// moving is possible // moving is possible
} } else {
else if (shortKnotValue == SKV_VALUE_INVALID) {
{
if (shortKnotValue == SKV_VALUE_INVALID)
{
PRINT(0, m, "ERROR: Moved from layer " << curState.layerNumber << " and state " << curState.stateNumber << " setSituation() returned false, although getPossibilities() yields some possible moves."); PRINT(0, m, "ERROR: Moved from layer " << curState.layerNumber << " and state " << curState.stateNumber << " setSituation() returned false, although getPossibilities() yields some possible moves.");
return m->falseOrStop(); return m->falseOrStop();
} }
// check each possibility // check each possibility
for (curPoss = 0; curPoss < knot.numPossibilities; curPoss++) for (curPoss = 0; curPoss < knot.numPossibilities; curPoss++) {
{
// move // move
m->move(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, &pBackup, pPossibilities); m->move(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, &pBackup, pPossibilities);
@ -541,8 +473,7 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index)
m->undo(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, pBackup, pPossibilities); m->undo(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, pBackup, pPossibilities);
// state reached by move() must not be invalid // state reached by move() must not be invalid
if (!m->setSituation(tlVars->curThreadNo, subState.layerNumber, subState.stateNumber)) if (!m->setSituation(tlVars->curThreadNo, subState.layerNumber, subState.stateNumber)) {
{
PRINT(0, m, "ERROR: Moved from layer " << curState.layerNumber << " and state " << curState.stateNumber << " to invalid situation layer " << curState.layerNumber << " and state " << curState.stateNumber); PRINT(0, m, "ERROR: Moved from layer " << curState.layerNumber << " and state " << curState.stateNumber << " to invalid situation layer " << curState.layerNumber << " and state " << curState.stateNumber);
return m->falseOrStop(); return m->falseOrStop();
} }
@ -575,16 +506,14 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
unsigned int i; unsigned int i;
// database open? // database open?
if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) {
{
PRINT(0, this, "ERROR: Database files not open!"); PRINT(0, this, "ERROR: Database files not open!");
layerNumber = 0; layerNumber = 0;
goto errorInDatabase; goto errorInDatabase;
} }
// layer completed ? // layer completed ?
if (!layerStats[layerNumber].layerIsCompletedAndInFile) if (!layerStats[layerNumber].layerIsCompletedAndInFile) {
{
PRINT(0, this, "ERROR: Layer not in file!"); PRINT(0, this, "ERROR: Layer not in file!");
layerNumber = 0; layerNumber = 0;
goto errorInDatabase; goto errorInDatabase;
@ -595,8 +524,7 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
PRINT(1, this, (getOutputInformation(layerNumber))); PRINT(1, this, (getOutputInformation(layerNumber)));
skvfHeader.completed = false; skvfHeader.completed = false;
for (layerInDatabase = false, stateNumber = 0; stateNumber < layerStats[layerNumber].knotsInLayer; stateNumber++) for (layerInDatabase = false, stateNumber = 0; stateNumber < layerStats[layerNumber].knotsInLayer; stateNumber++) {
{
// output // output
if (stateNumber % OUTPUT_EVERY_N_STATES == 0) if (stateNumber % OUTPUT_EVERY_N_STATES == 0)
@ -607,8 +535,7 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState);
// prepare the situation // prepare the situation
if (!setSituation(threadNo, layerNumber, stateNumber)) if (!setSituation(threadNo, layerNumber, stateNumber)) {
{
// when situation cannot be constructed then state must be marked as invalid in database // when situation cannot be constructed then state must be marked as invalid in database
if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID) if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID)
@ -621,14 +548,12 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers); getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers);
// save value for all symmetric states // save value for all symmetric states
for (i = 0; i < numSymmetricStates; i++) for (i = 0; i < numSymmetricStates; i++) {
{
readKnotValueFromDatabase(layerNumber, symStateNumbers[i], shortValueOfSymState); readKnotValueFromDatabase(layerNumber, symStateNumbers[i], shortValueOfSymState);
readPlyInfoFromDatabase(layerNumber, symStateNumbers[i], numPliesTillSymState); readPlyInfoFromDatabase(layerNumber, symStateNumbers[i], numPliesTillSymState);
if (shortValueOfSymState != shortValueInDatabase || numPliesTillCurState != numPliesTillSymState) if (shortValueOfSymState != shortValueInDatabase || numPliesTillCurState != numPliesTillSymState) {
{
PRINT(2, this, "current tested state " << stateNumber << " has value " << (int)shortValueInDatabase); PRINT(2, this, "current tested state " << stateNumber << " has value " << (int)shortValueInDatabase);
setSituation(threadNo, layerNumber, stateNumber); setSituation(threadNo, layerNumber, stateNumber);

File diff suppressed because it is too large Load Diff

View File

@ -62,12 +62,9 @@ void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int c
initialField.createBoard(); initialField.createBoard();
// calc beginning player // calc beginning player
if (currentPlayer == field.playerOne || currentPlayer == field.playerTwo) if (currentPlayer == field.playerOne || currentPlayer == field.playerTwo) {
{
beginningPlayer = currentPlayer; beginningPlayer = currentPlayer;
} } else {
else
{
beginningPlayer = (rand() % 2) ? field.playerOne : field.playerTwo; beginningPlayer = (rand() % 2) ? field.playerOne : field.playerTwo;
} }
field.curPlayer->id = beginningPlayer; field.curPlayer->id = beginningPlayer;
@ -106,10 +103,8 @@ void Position::setUpCalcPossibleMoves(Player *player)
// locals // locals
unsigned int i, j, k, movingDirection; unsigned int i, j, k, movingDirection;
for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) {
{ for (j = 0; j < fieldStruct::size; j++) {
for (j = 0; j < fieldStruct::size; j++)
{
// is stone from player ? // is stone from player ?
if (field.board[i] != player->id) if (field.board[i] != player->id)
@ -120,8 +115,7 @@ void Position::setUpCalcPossibleMoves(Player *player)
continue; continue;
// when current player has only 3 stones he is allowed to spring his stone // when current player has only 3 stones he is allowed to spring his stone
if (player->numStones > 3 || field.settingPhase) if (player->numStones > 3 || field.settingPhase) {
{
// determine moving direction // determine moving direction
for (k = 0, movingDirection = 4; k < 4; k++) for (k = 0, movingDirection = 4; k < 4; k++)
@ -149,8 +143,7 @@ void Position::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeig
int rowOwner = field.board[stone]; int rowOwner = field.board[stone];
// mill closed ? // mill closed ?
if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) {
{
field.stonePartOfMill[stone]++; field.stonePartOfMill[stone]++;
field.stonePartOfMill[firstNeighbour]++; field.stonePartOfMill[firstNeighbour]++;
@ -195,8 +188,7 @@ bool Position::put_piece(unsigned int pos, int player)
field.stonePartOfMill[i] = 0; field.stonePartOfMill[i] = 0;
// go in every direction // go in every direction
for (i = 0; i < fieldStruct::size; i++) for (i = 0; i < fieldStruct::size; i++) {
{
setUpSetWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1]); setUpSetWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1]);
setUpSetWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1]); setUpSetWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1]);
} }
@ -206,8 +198,7 @@ bool Position::put_piece(unsigned int pos, int player)
field.stonePartOfMill[i] /= 3; field.stonePartOfMill[i] /= 3;
// count completed mills // count completed mills
for (i = 0; i < fieldStruct::size; i++) for (i = 0; i < fieldStruct::size; i++) {
{
if (field.board[i] == field.curPlayer->id) if (field.board[i] == field.curPlayer->id)
numberOfMillsCurrentPlayer += field.stonePartOfMill[i]; numberOfMillsCurrentPlayer += field.stonePartOfMill[i];
else else
@ -217,15 +208,12 @@ bool Position::put_piece(unsigned int pos, int player)
numberOfMillsOpponentPlayer /= 3; numberOfMillsOpponentPlayer /= 3;
// stonesSet & numStonesMissing // stonesSet & numStonesMissing
if (field.settingPhase) if (field.settingPhase) {
{
// ... This calculation is not correct! It is possible that some mills did not cause a stone removal. // ... This calculation is not correct! It is possible that some mills did not cause a stone removal.
field.curPlayer->numStonesMissing = numberOfMillsOpponentPlayer; field.curPlayer->numStonesMissing = numberOfMillsOpponentPlayer;
field.oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - field.stoneMustBeRemoved; field.oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - field.stoneMustBeRemoved;
field.stonesSet = field.curPlayer->numStones + field.oppPlayer->numStones + field.curPlayer->numStonesMissing + field.oppPlayer->numStonesMissing; field.stonesSet = field.curPlayer->numStones + field.oppPlayer->numStones + field.curPlayer->numStonesMissing + field.oppPlayer->numStonesMissing;
} } else {
else
{
field.stonesSet = 18; field.stonesSet = 18;
field.curPlayer->numStonesMissing = 9 - field.curPlayer->numStones; field.curPlayer->numStonesMissing = 9 - field.curPlayer->numStones;
field.oppPlayer->numStonesMissing = 9 - field.oppPlayer->numStones; field.oppPlayer->numStonesMissing = 9 - field.oppPlayer->numStones;
@ -269,8 +257,7 @@ bool Position::getField(int *pField)
if (moveLogFrom == nullptr) if (moveLogFrom == nullptr)
return false; return false;
for (index = 0; index < field.size; index++) for (index = 0; index < field.size; index++) {
{
if (field.warnings[index] != field.noWarning) if (field.warnings[index] != field.noWarning)
pField[index] = (int)field.warnings[index]; pField[index] = (int)field.warnings[index];
else else
@ -290,8 +277,7 @@ void Position::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned i
numMovesDone = movesDone; numMovesDone = movesDone;
for (index = 0; index < movesDone; index++) for (index = 0; index < movesDone; index++) {
{
from[index] = moveLogFrom[index]; from[index] = moveLogFrom[index];
to[index] = moveLogTo[index]; to[index] = moveLogTo[index];
} }
@ -340,12 +326,10 @@ bool Position::isOpponentPlayerHuman()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Position::setAI(int player, MillAI *AI) void Position::setAI(int player, MillAI *AI)
{ {
if (player == field.playerOne) if (player == field.playerOne) {
{
playerOneAI = AI; playerOneAI = AI;
} }
if (player == field.playerTwo) if (player == field.playerTwo) {
{
playerTwoAI = AI; playerTwoAI = AI;
} }
} }
@ -378,15 +362,11 @@ void Position::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo)
theField.createBoard(); theField.createBoard();
field.copyBoard(&theField); field.copyBoard(&theField);
if ((field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) if ((field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) {
{ if (field.curPlayer->id == field.playerOne) {
if (field.curPlayer->id == field.playerOne)
{
if (playerOneAI != nullptr) if (playerOneAI != nullptr)
playerOneAI->play(&theField, pushFrom, pushTo); playerOneAI->play(&theField, pushFrom, pushTo);
} } else {
else
{
if (playerTwoAI != nullptr) if (playerTwoAI != nullptr)
playerTwoAI->play(&theField, pushFrom, pushTo); playerTwoAI->play(&theField, pushFrom, pushTo);
} }
@ -419,8 +399,7 @@ bool Position::isNormalMovePossible(unsigned int from, unsigned int to, Player *
return false; return false;
// when current player has only 3 stones he is allowed to spring his stone // when current player has only 3 stones he is allowed to spring his stone
if (player->numStones > 3 || field.settingPhase) if (player->numStones > 3 || field.settingPhase) {
{
// determine moving direction // determine moving direction
for (i = 0, movingDirection = 4; i < 4; i++) for (i = 0, movingDirection = 4; i < 4; i++)
@ -452,12 +431,9 @@ void Position::calcPossibleMoves(Player *player)
player->posFrom[i] = field.size; player->posFrom[i] = field.size;
// calc // calc
for (player->numPossibleMoves = 0, i = 0; i < field.size; i++) for (player->numPossibleMoves = 0, i = 0; i < field.size; i++) {
{ for (j = 0; j < field.size; j++) {
for (j = 0; j < field.size; j++) if (isNormalMovePossible(i, j, player)) {
{
if (isNormalMovePossible(i, j, player))
{
player->posFrom[player->numPossibleMoves] = i; player->posFrom[player->numPossibleMoves] = i;
player->posTo[player->numPossibleMoves] = j; player->posTo[player->numPossibleMoves] = j;
player->numPossibleMoves++; player->numPossibleMoves++;
@ -466,10 +442,8 @@ void Position::calcPossibleMoves(Player *player)
} }
// stoneMoveAble // stoneMoveAble
for (i = 0; i < field.size; i++) for (i = 0; i < field.size; i++) {
{ for (j = 0; j < 4; j++) {
for (j = 0; j < 4; j++)
{
if (field.board[i] == player->id) if (field.board[i] == player->id)
field.stoneMoveAble[i][j] = isNormalMovePossible(i, field.connectedSquare[i][j], player); field.stoneMoveAble[i][j] = isNormalMovePossible(i, field.connectedSquare[i][j], player);
else else
@ -489,8 +463,7 @@ void Position::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour
unsigned int rowOwnerWarning = (rowOwner == field.playerOne) ? field.playerOneWarning : field.playerTwoWarning; unsigned int rowOwnerWarning = (rowOwner == field.playerOne) ? field.playerOneWarning : field.playerTwoWarning;
// mill closed ? // mill closed ?
if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) {
{
field.stonePartOfMill[stone]++; field.stonePartOfMill[stone]++;
field.stonePartOfMill[firstNeighbour]++; field.stonePartOfMill[firstNeighbour]++;
@ -524,8 +497,7 @@ void Position::updateMillsAndWarnings(unsigned int newStone)
field.stoneMustBeRemoved = 0; field.stoneMustBeRemoved = 0;
// go in every direction // go in every direction
for (i = 0; i < field.size; i++) for (i = 0; i < field.size; i++) {
{
setWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1], i == newStone); setWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1], i == newStone);
setWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1], i == newStone); setWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1], i == newStone);
@ -558,8 +530,7 @@ bool Position::do_move(unsigned int pushFrom, unsigned int pushTo)
return false; return false;
// handle the remove of a stone // handle the remove of a stone
if (field.stoneMustBeRemoved) if (field.stoneMustBeRemoved) {
{
// parameter ok ? // parameter ok ?
if (pushFrom >= field.size) if (pushFrom >= field.size)
@ -605,9 +576,7 @@ bool Position::do_move(unsigned int pushFrom, unsigned int pushTo)
return true; return true;
// handle setting phase // handle setting phase
} } else if (field.settingPhase) {
else if (field.settingPhase)
{
// parameter ok ? // parameter ok ?
if (pushTo >= field.size) if (pushTo >= field.size)
@ -648,9 +617,7 @@ bool Position::do_move(unsigned int pushFrom, unsigned int pushTo)
return true; return true;
// normal move // normal move
} } else {
else
{
// is move possible ? // is move possible ?
if (!isNormalMovePossible(pushFrom, pushTo, field.curPlayer)) if (!isNormalMovePossible(pushFrom, pushTo, field.curPlayer))
@ -713,63 +680,51 @@ bool Position::compareWithField(fieldStruct *compareField)
unsigned int i, j; unsigned int i, j;
bool ret = true; bool ret = true;
if (!comparePlayers(field.curPlayer, compareField->curPlayer)) if (!comparePlayers(field.curPlayer, compareField->curPlayer)) {
{
cout << "error - curPlayer differs!" << endl; cout << "error - curPlayer differs!" << endl;
ret = false; ret = false;
} }
if (!comparePlayers(field.oppPlayer, compareField->oppPlayer)) if (!comparePlayers(field.oppPlayer, compareField->oppPlayer)) {
{
cout << "error - oppPlayer differs!" << endl; cout << "error - oppPlayer differs!" << endl;
ret = false; ret = false;
} }
if (field.stonesSet != compareField->stonesSet) if (field.stonesSet != compareField->stonesSet) {
{
cout << "error - stonesSet differs!" << endl; cout << "error - stonesSet differs!" << endl;
ret = false; ret = false;
} }
if (field.settingPhase != compareField->settingPhase) if (field.settingPhase != compareField->settingPhase) {
{
cout << "error - settingPhase differs!" << endl; cout << "error - settingPhase differs!" << endl;
ret = false; ret = false;
} }
if (field.stoneMustBeRemoved != compareField->stoneMustBeRemoved) if (field.stoneMustBeRemoved != compareField->stoneMustBeRemoved) {
{
cout << "error - stoneMustBeRemoved differs!" << endl; cout << "error - stoneMustBeRemoved differs!" << endl;
ret = false; ret = false;
} }
for (i = 0; i < field.size; i++) for (i = 0; i < field.size; i++) {
{
if (field.board[i] != compareField->board[i]) if (field.board[i] != compareField->board[i]) {
{
cout << "error - board[] differs!" << endl; cout << "error - board[] differs!" << endl;
ret = false; ret = false;
} }
if (field.warnings[i] != compareField->warnings[i]) if (field.warnings[i] != compareField->warnings[i]) {
{
cout << "error - warnings[] differs!" << endl; cout << "error - warnings[] differs!" << endl;
ret = false; ret = false;
} }
if (field.stonePartOfMill[i] != compareField->stonePartOfMill[i]) if (field.stonePartOfMill[i] != compareField->stonePartOfMill[i]) {
{
cout << "error - stonePart[] differs!" << endl; cout << "error - stonePart[] differs!" << endl;
ret = false; ret = false;
} }
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++) {
{
if (field.connectedSquare[i][j] != compareField->connectedSquare[i][j]) if (field.connectedSquare[i][j] != compareField->connectedSquare[i][j]) {
{
cout << "error - connectedSquare[] differs!" << endl; cout << "error - connectedSquare[] differs!" << endl;
ret = false; ret = false;
} }
// if (board.stoneMoveAble[i][j] != compareField->stoneMoveAble[i][j]) { cout << "error - stoneMoveAble differs!" << endl; ret = false; } // if (board.stoneMoveAble[i][j] != compareField->stoneMoveAble[i][j]) { cout << "error - stoneMoveAble differs!" << endl; ret = false; }
if (field.neighbour[i][j / 2][j % 2] != compareField->neighbour[i][j / 2][j % 2]) if (field.neighbour[i][j / 2][j % 2] != compareField->neighbour[i][j / 2][j % 2]) {
{
cout << "error - neighbour differs!" << endl; cout << "error - neighbour differs!" << endl;
ret = false; ret = false;
} }
@ -788,28 +743,23 @@ bool Position::comparePlayers(Player *playerA, Player *playerB)
// unsigned int i; // unsigned int i;
bool ret = true; bool ret = true;
if (playerA->numStonesMissing != playerB->numStonesMissing) if (playerA->numStonesMissing != playerB->numStonesMissing) {
{
cout << "error - numStonesMissing differs!" << endl; cout << "error - numStonesMissing differs!" << endl;
ret = false; ret = false;
} }
if (playerA->numStones != playerB->numStones) if (playerA->numStones != playerB->numStones) {
{
cout << "error - numStones differs!" << endl; cout << "error - numStones differs!" << endl;
ret = false; ret = false;
} }
if (playerA->id != playerB->id) if (playerA->id != playerB->id) {
{
cout << "error - id differs!" << endl; cout << "error - id differs!" << endl;
ret = false; ret = false;
} }
if (playerA->warning != playerB->warning) if (playerA->warning != playerB->warning) {
{
cout << "error - warning differs!" << endl; cout << "error - warning differs!" << endl;
ret = false; ret = false;
} }
if (playerA->numPossibleMoves != playerB->numPossibleMoves) if (playerA->numPossibleMoves != playerB->numPossibleMoves) {
{
cout << "error - numPossibleMoves differs!" << endl; cout << "error - numPossibleMoves differs!" << endl;
ret = false; ret = false;
} }
@ -843,12 +793,10 @@ void Position::undo_move(void)
unsigned int i; unsigned int i;
// at least one move must be done // at least one move must be done
if (movesDone) if (movesDone) {
{
// make backup of log // make backup of log
for (i = 0; i < movesDone; i++) for (i = 0; i < movesDone; i++) {
{
moveLogFrom_bak[i] = moveLogFrom[i]; moveLogFrom_bak[i] = moveLogFrom[i];
moveLogTo_bak[i] = moveLogTo[i]; moveLogTo_bak[i] = moveLogTo[i];
} }
@ -859,8 +807,7 @@ void Position::undo_move(void)
movesDone = 0; movesDone = 0;
// and play again // and play again
for (i = 0; i < movesDone_bak - 1; i++) for (i = 0; i < movesDone_bak - 1; i++) {
{
do_move(moveLogFrom_bak[i], moveLogTo_bak[i]); do_move(moveLogFrom_bak[i], moveLogTo_bak[i]);
} }
} }
@ -876,13 +823,10 @@ void Position::undo_move(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Position::calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting) void Position::calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting)
{ {
if (getCurrentPlayer() == fieldStruct::playerTwo) if (getCurrentPlayer() == fieldStruct::playerTwo) {
{
numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones;
numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones;
} } else {
else
{
numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones;
numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones;
} }

View File

@ -38,55 +38,41 @@ void RandomAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
bool allowedToSpring = (theField->curPlayer->numStones == 3) ? true : false; bool allowedToSpring = (theField->curPlayer->numStones == 3) ? true : false;
// must stone be removed ? // must stone be removed ?
if (theField->stoneMustBeRemoved) if (theField->stoneMustBeRemoved) {
{
// search a stone from the enemy // search a stone from the enemy
do do {
{
from = rand() % theField->size; from = rand() % theField->size;
to = theField->size; to = theField->size;
} while (theField->board[from] != theField->oppPlayer->id || theField->stonePartOfMill[from]); } while (theField->board[from] != theField->oppPlayer->id || theField->stonePartOfMill[from]);
// still in setting phase ? // still in setting phase ?
} } else if (theField->settingPhase) {
else if (theField->settingPhase)
{
// search a free square // search a free square
do do {
{
from = theField->size; from = theField->size;
to = rand() % theField->size; to = rand() % theField->size;
} while (theField->board[to] != theField->squareIsFree); } while (theField->board[to] != theField->squareIsFree);
// try to push randomly // try to push randomly
} } else {
else
{
do do {
{
// search an own stone // search an own stone
do do {
{
from = rand() % theField->size; from = rand() % theField->size;
} while (theField->board[from] != theField->curPlayer->id); } while (theField->board[from] != theField->curPlayer->id);
// select a free square // select a free square
if (allowedToSpring) if (allowedToSpring) {
{ do {
do
{
to = rand() % theField->size; to = rand() % theField->size;
} while (theField->board[to] != theField->squareIsFree); } while (theField->board[to] != theField->squareIsFree);
// select a connected square // select a connected square
} } else {
else do {
{
do
{
direction = rand() % 4; direction = rand() % 4;
to = theField->connectedSquare[from][direction]; to = theField->connectedSquare[from][direction];
} while (to == theField->size); } while (to == theField->size);

View File

@ -54,13 +54,11 @@ MyString::MyString(const WCHAR *cStr)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
MyString::~MyString() MyString::~MyString()
{ {
if (strA != nullptr) if (strA != nullptr) {
{
delete[] strA; delete[] strA;
strA = nullptr; strA = nullptr;
} }
if (strW != nullptr) if (strW != nullptr) {
{
delete[] strW; delete[] strW;
strW = nullptr; strW = nullptr;
} }
@ -167,7 +165,7 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
bool expIsNegativ = false; bool expIsNegativ = false;
bool decimalPlace = false; bool decimalPlace = false;
bool exponent = false; bool exponent = false;
double fractionalFactor[] = {0, double fractionalFactor[] = { 0,
0.1, 0.1,
0.01, 0.01,
0.001, 0.001,
@ -177,15 +175,13 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
0.0000001, 0.0000001,
0.00000001, 0.00000001,
0.000000001, 0.000000001,
0.0000000001}; 0.0000000001 };
// read each value // read each value
do do {
{
// read from buffer if necessary // read from buffer if necessary
if (curBufferPos >= bufferSize - maxValueLengthInBytes) if (curBufferPos >= bufferSize - maxValueLengthInBytes) {
{
memcpy(&buffer[0], &buffer[curBufferPos], bufferSize - curBufferPos); memcpy(&buffer[0], &buffer[curBufferPos], bufferSize - curBufferPos);
ReadFile(hFile, &buffer[bufferSize - curBufferPos], curBufferPos, &dwBytesRead, nullptr); ReadFile(hFile, &buffer[bufferSize - curBufferPos], curBufferPos, &dwBytesRead, nullptr);
actualBufferSize = bufferSize - curBufferPos + dwBytesRead; actualBufferSize = bufferSize - curBufferPos + dwBytesRead;
@ -194,15 +190,11 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
} }
// process current byte // process current byte
switch (*curByte) switch (*curByte) {
{
case '-': case '-':
if (exponent) if (exponent) {
{
expIsNegativ = true; expIsNegativ = true;
} } else {
else
{
valIsNegativ = true; valIsNegativ = true;
} }
break; break;
@ -214,213 +206,156 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
decimalPlace = false; decimalPlace = false;
break; break;
case '0': case '0':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 0; fractionalValue += 0;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 0; exponentialValue += 0;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 0; integralValue += 0;
} }
break; break;
case '1': case '1':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 1; fractionalValue += 1;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 1; exponentialValue += 1;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 1; integralValue += 1;
} }
break; break;
case '2': case '2':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 2; fractionalValue += 2;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 2; exponentialValue += 2;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 2; integralValue += 2;
} }
break; break;
case '3': case '3':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 3; fractionalValue += 3;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 3; exponentialValue += 3;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 3; integralValue += 3;
} }
break; break;
case '4': case '4':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 4; fractionalValue += 4;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 4; exponentialValue += 4;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 4; integralValue += 4;
} }
break; break;
case '5': case '5':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 5; fractionalValue += 5;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 5; exponentialValue += 5;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 5; integralValue += 5;
} }
break; break;
case '6': case '6':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 6; fractionalValue += 6;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 6; exponentialValue += 6;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 6; integralValue += 6;
} }
break; break;
case '7': case '7':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 7; fractionalValue += 7;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 7; exponentialValue += 7;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 7; integralValue += 7;
} }
break; break;
case '8': case '8':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 8; fractionalValue += 8;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 8; exponentialValue += 8;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 8; integralValue += 8;
} }
break; break;
case '9': case '9':
if (decimalPlace) if (decimalPlace) {
{
fractionalValue *= 10; fractionalValue *= 10;
fractionalValue += 9; fractionalValue += 9;
decimalPos++; decimalPos++;
} } else if (exponent) {
else if (exponent)
{
exponentialValue *= 10; exponentialValue *= 10;
exponentialValue += 9; exponentialValue += 9;
} } else {
else
{
integralValue *= 10; integralValue *= 10;
integralValue += 9; integralValue += 9;
} }
break; break;
default: default:
if (*curByte == decimalSeperator) if (*curByte == decimalSeperator) {
{
decimalPlace = true; decimalPlace = true;
exponent = false; exponent = false;
} } else if (*curByte == columnSeparator) {
else if (*curByte == columnSeparator)
{
// everything ok? // everything ok?
if (decimalPos > 8) if (decimalPos > 8) {
{
cout << "ERROR in function readAsciiData(): Too many digits on decimal place. Maximum is 8 !" << endl; cout << "ERROR in function readAsciiData(): Too many digits on decimal place. Maximum is 8 !" << endl;
return false; return false;
} }
// calc final value // calc final value
(*pData) = integralValue; (*pData) = integralValue;
if (decimalPos) if (decimalPos) {
{
(*pData) += fractionalValue * fractionalFactor[decimalPos]; (*pData) += fractionalValue * fractionalFactor[decimalPos];
} }
if (valIsNegativ) if (valIsNegativ) {
{
(*pData) *= -1; (*pData) *= -1;
} }
if (exponent) if (exponent) {
{
(*pData) *= pow(10, expIsNegativ ? -1 * exponentialValue : 1); (*pData) *= pow(10, expIsNegativ ? -1 * exponentialValue : 1);
} }
@ -437,9 +372,7 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
// save value // save value
pData++; pData++;
curReadValue++; curReadValue++;
} } else {
else
{
// do nothing // do nothing
} }
break; break;

View File

@ -16,7 +16,7 @@ ThreadManager::ThreadManager()
{ {
// locals // locals
unsigned int curThreadNo; unsigned int curThreadNo;
SYSTEM_INFO m_si = {0}; SYSTEM_INFO m_si = { 0 };
GetSystemInfo(&m_si); GetSystemInfo(&m_si);
@ -32,8 +32,7 @@ ThreadManager::ThreadManager()
InitializeCriticalSection(&csBarrier); InitializeCriticalSection(&csBarrier);
hEventBarrierPassedByEveryBody = CreateEvent(nullptr, true, false, nullptr); hEventBarrierPassedByEveryBody = CreateEvent(nullptr, true, false, nullptr);
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
hThread[curThreadNo] = nullptr; hThread[curThreadNo] = nullptr;
threadId[curThreadNo] = 0; threadId[curThreadNo] = 0;
hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr);
@ -49,8 +48,7 @@ ThreadManager::~ThreadManager()
// locals // locals
unsigned int curThreadNo; unsigned int curThreadNo;
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
CloseHandle(hBarrier[curThreadNo]); CloseHandle(hBarrier[curThreadNo]);
} }
@ -76,8 +74,7 @@ void ThreadManager::waitForOtherThreads(unsigned int threadNo)
{ {
// wait if other threads are still waiting at the barrier // wait if other threads are still waiting at the barrier
//cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "while (numThreadsPassedBarrier>0)"; //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "while (numThreadsPassedBarrier>0)";
if (numThreadsPassedBarrier > 0) if (numThreadsPassedBarrier > 0) {
{
WaitForSingleObject(hEventBarrierPassedByEveryBody, INFINITE); WaitForSingleObject(hEventBarrierPassedByEveryBody, INFINITE);
} }
@ -92,8 +89,7 @@ void ThreadManager::waitForOtherThreads(unsigned int threadNo)
EnterCriticalSection(&csBarrier); EnterCriticalSection(&csBarrier);
// if the first one which entered, then wait until other threads // if the first one which entered, then wait until other threads
if (numThreadsPassedBarrier == 0) if (numThreadsPassedBarrier == 0) {
{
//cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "WaitForMultipleObjects()"; //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "WaitForMultipleObjects()";
WaitForMultipleObjects(numThreads, hBarrier, TRUE, INFINITE); WaitForMultipleObjects(numThreads, hBarrier, TRUE, INFINITE);
ResetEvent(hEventBarrierPassedByEveryBody); ResetEvent(hEventBarrierPassedByEveryBody);
@ -105,8 +101,7 @@ void ThreadManager::waitForOtherThreads(unsigned int threadNo)
// the last one closes the door // the last one closes the door
//cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "if (numThreadsPassedBarrier == numThreads) numThreadsPassedBarrier = 0"; //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "if (numThreadsPassedBarrier == numThreads) numThreadsPassedBarrier = 0";
if (numThreadsPassedBarrier == numThreads) if (numThreadsPassedBarrier == numThreads) {
{
numThreadsPassedBarrier = 0; numThreadsPassedBarrier = 0;
SetEvent(hEventBarrierPassedByEveryBody); SetEvent(hEventBarrierPassedByEveryBody);
} }
@ -132,18 +127,15 @@ bool ThreadManager::setNumThreads(unsigned int newNumThreads)
{ {
// cancel if any thread running // cancel if any thread running
EnterCriticalSection(&csBarrier); EnterCriticalSection(&csBarrier);
for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
if (hThread[curThreadNo]) if (hThread[curThreadNo])
return false; return false;
} }
for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
CloseHandle(hBarrier[curThreadNo]); CloseHandle(hBarrier[curThreadNo]);
} }
numThreads = newNumThreads; numThreads = newNumThreads;
for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr);
} }
LeaveCriticalSection(&csBarrier); LeaveCriticalSection(&csBarrier);
@ -156,17 +148,13 @@ bool ThreadManager::setNumThreads(unsigned int newNumThreads)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ThreadManager::pauseExecution() void ThreadManager::pauseExecution()
{ {
for (unsigned int curThread = 0; curThread < numThreads; curThread++) for (unsigned int curThread = 0; curThread < numThreads; curThread++) {
{
// unsuspend all threads // unsuspend all threads
if (!executionPaused) if (!executionPaused) {
{
SuspendThread(hThread[curThread]); SuspendThread(hThread[curThread]);
// suspend all threads // suspend all threads
} } else {
else
{
ResumeThread(hThread[curThread]); ResumeThread(hThread[curThread]);
} }
} }
@ -182,8 +170,7 @@ void ThreadManager::cancelExecution()
{ {
termineAllThreads = true; termineAllThreads = true;
executionCancelled = true; executionCancelled = true;
if (executionPaused) if (executionPaused) {
{
pauseExecution(); pauseExecution();
} }
} }
@ -216,10 +203,8 @@ unsigned int ThreadManager::getThreadNumber()
DWORD curThreadId = GetCurrentThreadId(); DWORD curThreadId = GetCurrentThreadId();
unsigned int curThreadNo; unsigned int curThreadNo;
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{ if (curThreadId == threadId[curThreadNo]) {
if (curThreadId == threadId[curThreadNo])
{
return curThreadNo; return curThreadNo;
} }
} }
@ -244,16 +229,13 @@ unsigned int ThreadManager::executeInParallel(DWORD threadProc(void *pParameter)
termineAllThreads = false; termineAllThreads = false;
// create threads // create threads
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, (LPTHREAD_START_ROUTINE)threadProc, (void *)(((char *)pParameter) + curThreadNo * parameterStructSize), CREATE_SUSPENDED, &threadId[curThreadNo]); hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, (LPTHREAD_START_ROUTINE)threadProc, (void *)(((char *)pParameter) + curThreadNo * parameterStructSize), CREATE_SUSPENDED, &threadId[curThreadNo]);
SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL); SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL);
if (hThread[curThreadNo] == nullptr) if (hThread[curThreadNo] == nullptr) {
{ for (curThreadNo; curThreadNo > 0; curThreadNo--) {
for (curThreadNo; curThreadNo > 0; curThreadNo--)
{
CloseHandle(hThread[curThreadNo - 1]); CloseHandle(hThread[curThreadNo - 1]);
hThread[curThreadNo - 1] = nullptr; hThread[curThreadNo - 1] = nullptr;
} }
@ -262,8 +244,7 @@ unsigned int ThreadManager::executeInParallel(DWORD threadProc(void *pParameter)
} }
// start threads // start threads
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
if (!executionPaused) if (!executionPaused)
ResumeThread(hThread[curThreadNo]); ResumeThread(hThread[curThreadNo]);
} }
@ -272,20 +253,16 @@ unsigned int ThreadManager::executeInParallel(DWORD threadProc(void *pParameter)
WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
// Close all thread handles upon completion. // Close all thread handles upon completion.
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
CloseHandle(hThread[curThreadNo]); CloseHandle(hThread[curThreadNo]);
hThread[curThreadNo] = nullptr; hThread[curThreadNo] = nullptr;
threadId[curThreadNo] = 0; threadId[curThreadNo] = 0;
} }
// everything ok // everything ok
if (executionCancelled) if (executionCancelled) {
{
return TM_RETURN_VALUE_EXECUTION_CANCELLED; return TM_RETURN_VALUE_EXECUTION_CANCELLED;
} } else {
else
{
return TM_RETURN_VALUE_OK; return TM_RETURN_VALUE_OK;
} }
} }
@ -327,8 +304,7 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
termineAllThreads = false; termineAllThreads = false;
// create threads // create threads
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
forLoopParameters[curThreadNo].pParameter = (pParameter != nullptr ? (void *)(((char *)pParameter) + curThreadNo * parameterStructSize) : nullptr); forLoopParameters[curThreadNo].pParameter = (pParameter != nullptr ? (void *)(((char *)pParameter) + curThreadNo * parameterStructSize) : nullptr);
forLoopParameters[curThreadNo].threadManager = this; forLoopParameters[curThreadNo].threadManager = this;
@ -336,16 +312,12 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
forLoopParameters[curThreadNo].inkrement = inkrement; forLoopParameters[curThreadNo].inkrement = inkrement;
forLoopParameters[curThreadNo].scheduleType = scheduleType; forLoopParameters[curThreadNo].scheduleType = scheduleType;
switch (scheduleType) switch (scheduleType) {
{
case TM_SCHEDULE_STATIC: case TM_SCHEDULE_STATIC:
chunkSize = numIterations / numThreads + (curThreadNo < numIterations % numThreads ? 1 : 0); chunkSize = numIterations / numThreads + (curThreadNo < numIterations %numThreads ? 1 : 0);
if (curThreadNo == 0) if (curThreadNo == 0) {
{
forLoopParameters[curThreadNo].initialValue = initialValue; forLoopParameters[curThreadNo].initialValue = initialValue;
} } else {
else
{
forLoopParameters[curThreadNo].initialValue = forLoopParameters[curThreadNo - 1].finalValue + 1; forLoopParameters[curThreadNo].initialValue = forLoopParameters[curThreadNo - 1].finalValue + 1;
} }
forLoopParameters[curThreadNo].finalValue = forLoopParameters[curThreadNo].initialValue + chunkSize - 1; forLoopParameters[curThreadNo].finalValue = forLoopParameters[curThreadNo].initialValue + chunkSize - 1;
@ -364,10 +336,8 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
// create suspended thread // create suspended thread
hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, threadForLoop, (LPVOID)(&forLoopParameters[curThreadNo]), CREATE_SUSPENDED, &threadId[curThreadNo]); hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, threadForLoop, (LPVOID)(&forLoopParameters[curThreadNo]), CREATE_SUSPENDED, &threadId[curThreadNo]);
SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL); SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL);
if (hThread[curThreadNo] == nullptr) if (hThread[curThreadNo] == nullptr) {
{ for (curThreadNo; curThreadNo > 0; curThreadNo--) {
for (curThreadNo; curThreadNo > 0; curThreadNo--)
{
CloseHandle(hThread[curThreadNo - 1]); CloseHandle(hThread[curThreadNo - 1]);
hThread[curThreadNo - 1] = nullptr; hThread[curThreadNo - 1] = nullptr;
} }
@ -378,8 +348,7 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
} }
// start threads, but don't resume if in pause mode // start threads, but don't resume if in pause mode
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
if (!executionPaused) if (!executionPaused)
ResumeThread(hThread[curThreadNo]); ResumeThread(hThread[curThreadNo]);
} }
@ -388,8 +357,7 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
// Close all thread handles upon completion. // Close all thread handles upon completion.
for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) {
{
CloseHandle(hThread[curThreadNo]); CloseHandle(hThread[curThreadNo]);
hThread[curThreadNo] = nullptr; hThread[curThreadNo] = nullptr;
threadId[curThreadNo] = 0; threadId[curThreadNo] = 0;
@ -397,12 +365,9 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
delete[] forLoopParameters; delete[] forLoopParameters;
// everything ok // everything ok
if (executionCancelled) if (executionCancelled) {
{
return TM_RETURN_VALUE_EXECUTION_CANCELLED; return TM_RETURN_VALUE_EXECUTION_CANCELLED;
} } else {
else
{
return TM_RETURN_VALUE_OK; return TM_RETURN_VALUE_OK;
} }
} }
@ -417,13 +382,10 @@ DWORD WINAPI ThreadManager::threadForLoop(LPVOID lpParameter)
ForLoop *forLoopParameters = (ForLoop *)lpParameter; ForLoop *forLoopParameters = (ForLoop *)lpParameter;
int index; int index;
switch (forLoopParameters->scheduleType) switch (forLoopParameters->scheduleType) {
{
case TM_SCHEDULE_STATIC: case TM_SCHEDULE_STATIC:
for (index = forLoopParameters->initialValue; (forLoopParameters->inkrement < 0) ? index >= forLoopParameters->finalValue : index <= forLoopParameters->finalValue; index += forLoopParameters->inkrement) for (index = forLoopParameters->initialValue; (forLoopParameters->inkrement < 0) ? index >= forLoopParameters->finalValue : index <= forLoopParameters->finalValue; index += forLoopParameters->inkrement) {
{ switch (forLoopParameters->threadProc(forLoopParameters->pParameter, index)) {
switch (forLoopParameters->threadProc(forLoopParameters->pParameter, index))
{
case TM_RETURN_VALUE_OK: case TM_RETURN_VALUE_OK:
break; break;
case TM_RETURN_VALUE_TERMINATE_ALL_THREADS: case TM_RETURN_VALUE_TERMINATE_ALL_THREADS:

View File

@ -47,7 +47,7 @@ private:
int initialValue; int initialValue;
int finalValue; int finalValue;
void *pParameter; void *pParameter;
DWORD (*threadProc) DWORD(*threadProc)
(void *pParameter, int index); // pointer to the user function to be executed by the threads (void *pParameter, int index); // pointer to the user function to be executed by the threads
ThreadManager *threadManager; ThreadManager *threadManager;
}; };
@ -75,9 +75,15 @@ public:
public: public:
unsigned int curThreadNo; unsigned int curThreadNo;
virtual void initializeElement(){}; virtual void initializeElement()
virtual void destroyElement(){}; {
virtual void reduce(){}; };
virtual void destroyElement()
{
};
virtual void reduce()
{
};
}; };
template <class varType> template <class varType>
@ -92,8 +98,7 @@ public:
this->numberOfThreads = numberOfThreads; this->numberOfThreads = numberOfThreads;
this->item = new varType[numberOfThreads]; this->item = new varType[numberOfThreads];
for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) {
{
item[threadCounter].curThreadNo = threadCounter; item[threadCounter].curThreadNo = threadCounter;
item[threadCounter].initializeElement(master); item[threadCounter].initializeElement(master);
item[threadCounter].curThreadNo = threadCounter; // if 'curThreadNo' is overwritten in 'initializeElement()' item[threadCounter].curThreadNo = threadCounter; // if 'curThreadNo' is overwritten in 'initializeElement()'
@ -102,8 +107,7 @@ public:
~ThreadVarsArray() ~ThreadVarsArray()
{ {
for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) {
{
item[threadCounter].destroyElement(); item[threadCounter].destroyElement();
} }
delete[] item; delete[] item;
@ -121,8 +125,7 @@ public:
void reduce() void reduce()
{ {
for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) {
{
item[threadCounter].reduce(); item[threadCounter].reduce();
} }
}; };