From f74762d2c769952ddb4d32a37ecb91f122590a3b Mon Sep 17 00:00:00 2001 From: Calcitem Date: Wed, 20 Jan 2021 01:38:08 +0800 Subject: [PATCH] perfect: Format code with msvc --- src/perfect/bufferedFile.cpp | 277 +- src/perfect/bufferedFile.h | 60 +- src/perfect/config.h | 10 +- src/perfect/cyclicArray.cpp | 492 +-- src/perfect/cyclicArray.h | 56 +- src/perfect/main.cpp | 42 +- src/perfect/millAI.cpp | 340 +- src/perfect/millAI.h | 116 +- src/perfect/minMaxKI.cpp | 808 ++-- src/perfect/miniMax.cpp | 392 +- src/perfect/miniMax.h | 1154 ++--- src/perfect/miniMaxAI.h | 216 +- src/perfect/miniMaxWin.h | 146 +- src/perfect/miniMax_alphaBetaAlgorithmn.cpp | 1072 +++-- src/perfect/miniMax_database.cpp | 983 ++--- src/perfect/miniMax_retroAnalysis.cpp | 1292 +++--- src/perfect/miniMax_retroAnalysis.h | 82 +- src/perfect/miniMax_statistics.cpp | 430 +- src/perfect/miniMax_test.cpp | 997 ++--- src/perfect/perfectAI.cpp | 4185 +++++++++---------- src/perfect/perfectAI.h | 296 +- src/perfect/position.cpp | 1056 +++-- src/perfect/position.h | 178 +- src/perfect/randomAI.cpp | 110 +- src/perfect/randomAI.h | 20 +- src/perfect/strLib.cpp | 645 ++- src/perfect/strLib.h | 42 +- src/perfect/threadManager.cpp | 570 ++- src/perfect/threadManager.h | 195 +- 29 files changed, 7717 insertions(+), 8545 deletions(-) diff --git a/src/perfect/bufferedFile.cpp b/src/perfect/bufferedFile.cpp index 9eca3887..b76e3b1c 100644 --- a/src/perfect/bufferedFile.cpp +++ b/src/perfect/bufferedFile.cpp @@ -1,9 +1,9 @@ /********************************************************************* - bufferedFile.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + bufferedFile.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "bufferedFile.h" @@ -14,40 +14,38 @@ //----------------------------------------------------------------------------- BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSizeInBytes, const char *fileName) { - // locals - unsigned int curThread; + // locals + unsigned int curThread; - // Init blocks - bufferSize = bufferSizeInBytes; - numThreads = numberOfThreads; - readBuffer = new unsigned char[numThreads * bufferSize]; - writeBuffer = new unsigned char[numThreads * bufferSize]; - curWritingPointer = new long long[numThreads]; - curReadingPointer = new long long[numThreads]; - bytesInReadBuffer = new unsigned int[numThreads]; - bytesInWriteBuffer = new unsigned int[numThreads]; + // Init blocks + bufferSize = bufferSizeInBytes; + numThreads = numberOfThreads; + readBuffer = new unsigned char[numThreads * bufferSize]; + writeBuffer = new unsigned char[numThreads * bufferSize]; + curWritingPointer = new long long[numThreads]; + curReadingPointer = new long long[numThreads]; + bytesInReadBuffer = new unsigned int[numThreads]; + bytesInWriteBuffer = new unsigned int[numThreads]; - for (curThread = 0; curThread < numThreads; curThread++) - { - curReadingPointer[curThread] = 0; - curWritingPointer[curThread] = 0; - bytesInReadBuffer[curThread] = 0; - bytesInWriteBuffer[curThread] = 0; - } - InitializeCriticalSection(&csIO); + for (curThread = 0; curThread < numThreads; curThread++) { + curReadingPointer[curThread] = 0; + curWritingPointer[curThread] = 0; + bytesInReadBuffer[curThread] = 0; + bytesInWriteBuffer[curThread] = 0; + } + InitializeCriticalSection(&csIO); - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - // opened file succesfully - if (hFile == INVALID_HANDLE_VALUE) - { - hFile = nullptr; - return; - } + // opened file succesfully + if (hFile == INVALID_HANDLE_VALUE) { + hFile = nullptr; + return; + } - // update file size - getFileSize(); + // update file size + getFileSize(); } //----------------------------------------------------------------------------- @@ -56,21 +54,21 @@ BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSize //----------------------------------------------------------------------------- BufferedFile::~BufferedFile() { - // flush buffers - flushBuffers(); - DeleteCriticalSection(&csIO); + // flush buffers + flushBuffers(); + DeleteCriticalSection(&csIO); - // delete arrays - delete[] readBuffer; - delete[] writeBuffer; - delete[] curReadingPointer; - delete[] curWritingPointer; - delete[] bytesInReadBuffer; - delete[] bytesInWriteBuffer; + // delete arrays + delete[] readBuffer; + delete[] writeBuffer; + delete[] curReadingPointer; + delete[] curWritingPointer; + delete[] bytesInReadBuffer; + delete[] bytesInWriteBuffer; - // close file - if (hFile != nullptr) - CloseHandle(hFile); + // close file + if (hFile != nullptr) + CloseHandle(hFile); } //----------------------------------------------------------------------------- @@ -79,10 +77,10 @@ BufferedFile::~BufferedFile() //----------------------------------------------------------------------------- long long BufferedFile::getFileSize() { - LARGE_INTEGER liFileSize; - GetFileSizeEx(hFile, &liFileSize); - fileSize = liFileSize.QuadPart; - return fileSize; + LARGE_INTEGER liFileSize; + GetFileSizeEx(hFile, &liFileSize); + fileSize = liFileSize.QuadPart; + return fileSize; } //----------------------------------------------------------------------------- @@ -91,12 +89,11 @@ long long BufferedFile::getFileSize() //----------------------------------------------------------------------------- bool BufferedFile::flushBuffers() { - for (unsigned int threadNo = 0; threadNo < numThreads; threadNo++) - { - writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); - bytesInWriteBuffer[threadNo] = 0; - } - return true; + for (unsigned int threadNo = 0; threadNo < numThreads; threadNo++) { + writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); + bytesInWriteBuffer[threadNo] = 0; + } + return true; } //----------------------------------------------------------------------------- @@ -105,33 +102,29 @@ bool BufferedFile::flushBuffers() //----------------------------------------------------------------------------- void BufferedFile::writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData) { - DWORD dwBytesWritten; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = sizeInBytes; + DWORD dwBytesWritten; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = sizeInBytes; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - EnterCriticalSection(&csIO); - while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - cout << endl - << "SetFilePointerEx failed!"; - while (restingBytes > 0) - { - if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) - { - restingBytes -= dwBytesWritten; - pData = (void *)(((unsigned char *)pData) + dwBytesWritten); - if (restingBytes > 0) - cout << endl - << "Still " << restingBytes << " to write!"; - } - else - { - cout << endl - << "WriteFile Failed!"; - } - } - LeaveCriticalSection(&csIO); + EnterCriticalSection(&csIO); + while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) + cout << endl + << "SetFilePointerEx failed!"; + while (restingBytes > 0) { + if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) { + restingBytes -= dwBytesWritten; + pData = (void *)(((unsigned char *)pData) + dwBytesWritten); + if (restingBytes > 0) + cout << endl + << "Still " << restingBytes << " to write!"; + } else { + cout << endl + << "WriteFile Failed!"; + } + } + LeaveCriticalSection(&csIO); } //----------------------------------------------------------------------------- @@ -140,33 +133,29 @@ void BufferedFile::writeDataToFile(HANDLE hFile, long long offset, unsigned int //----------------------------------------------------------------------------- void BufferedFile::readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData) { - DWORD dwBytesRead; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = sizeInBytes; + DWORD dwBytesRead; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = sizeInBytes; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - EnterCriticalSection(&csIO); - while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - cout << endl - << "SetFilePointerEx failed!"; - while (restingBytes > 0) - { - if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) - { - restingBytes -= dwBytesRead; - pData = (void *)(((unsigned char *)pData) + dwBytesRead); - if (restingBytes > 0) - cout << endl - << "Still " << restingBytes << " to read!"; - } - else - { - cout << endl - << "ReadFile Failed!"; - } - } - LeaveCriticalSection(&csIO); + EnterCriticalSection(&csIO); + while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) + cout << endl + << "SetFilePointerEx failed!"; + while (restingBytes > 0) { + if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) { + restingBytes -= dwBytesRead; + pData = (void *)(((unsigned char *)pData) + dwBytesRead); + if (restingBytes > 0) + cout << endl + << "Still " << restingBytes << " to read!"; + } else { + cout << endl + << "ReadFile Failed!"; + } + } + LeaveCriticalSection(&csIO); } //----------------------------------------------------------------------------- @@ -175,7 +164,7 @@ void BufferedFile::readDataFromFile(HANDLE hFile, long long offset, unsigned int //----------------------------------------------------------------------------- bool BufferedFile::writeBytes(unsigned int numBytes, unsigned char *pData) { - return writeBytes(0, curWritingPointer[0], numBytes, pData); + return writeBytes(0, curWritingPointer[0], numBytes, pData); } //----------------------------------------------------------------------------- @@ -184,29 +173,28 @@ bool BufferedFile::writeBytes(unsigned int numBytes, unsigned char *pData) //----------------------------------------------------------------------------- bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData) { - // parameters ok? - if (threadNo >= numThreads) - return false; - if (pData == nullptr) - return false; + // parameters ok? + if (threadNo >= numThreads) + return false; + if (pData == nullptr) + return false; - // locals + // locals - // if buffer full or not sequential write operation write buffer to file - if (bytesInWriteBuffer[threadNo] && (positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) - { + // if buffer full or not sequential write operation write buffer to file + if (bytesInWriteBuffer[threadNo] && (positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) { - writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); - bytesInWriteBuffer[threadNo] = 0; - } + writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]); + bytesInWriteBuffer[threadNo] = 0; + } - // copy data into buffer - memcpy(&writeBuffer[threadNo * bufferSize + bytesInWriteBuffer[threadNo]], pData, numBytes); - bytesInWriteBuffer[threadNo] += numBytes; - curWritingPointer[threadNo] = positionInFile + numBytes; + // copy data into buffer + memcpy(&writeBuffer[threadNo * bufferSize + bytesInWriteBuffer[threadNo]], pData, numBytes); + bytesInWriteBuffer[threadNo] += numBytes; + curWritingPointer[threadNo] = positionInFile + numBytes; - // everything ok - return true; + // everything ok + return true; } //----------------------------------------------------------------------------- @@ -215,7 +203,7 @@ bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, u //----------------------------------------------------------------------------- bool BufferedFile::readBytes(unsigned int numBytes, unsigned char *pData) { - return readBytes(0, curReadingPointer[0], numBytes, pData); + return readBytes(0, curReadingPointer[0], numBytes, pData); } //----------------------------------------------------------------------------- @@ -224,24 +212,23 @@ bool BufferedFile::readBytes(unsigned int numBytes, unsigned char *pData) //----------------------------------------------------------------------------- bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData) { - // parameters ok? - if (threadNo >= numThreads) - return false; - if (pData == nullptr) - return false; + // parameters ok? + if (threadNo >= numThreads) + return false; + if (pData == nullptr) + return false; - // 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) - { - bytesInReadBuffer[threadNo] = ((positionInFile + bufferSize <= fileSize) ? bufferSize : (unsigned int)(fileSize - positionInFile)); - if (bytesInReadBuffer[threadNo] < numBytes) - return false; - readDataFromFile(hFile, positionInFile, bytesInReadBuffer[threadNo], &readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]]); - } - memcpy(pData, &readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]], numBytes); - bytesInReadBuffer[threadNo] -= numBytes; - curReadingPointer[threadNo] = positionInFile + numBytes; + // 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) { + bytesInReadBuffer[threadNo] = ((positionInFile + bufferSize <= fileSize) ? bufferSize : (unsigned int)(fileSize - positionInFile)); + if (bytesInReadBuffer[threadNo] < numBytes) + return false; + readDataFromFile(hFile, positionInFile, bytesInReadBuffer[threadNo], &readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]]); + } + memcpy(pData, &readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]], numBytes); + bytesInReadBuffer[threadNo] -= numBytes; + curReadingPointer[threadNo] = positionInFile + numBytes; - // everything ok - return true; + // everything ok + return true; } \ No newline at end of file diff --git a/src/perfect/bufferedFile.h b/src/perfect/bufferedFile.h index 5cad8182..11c02f8d 100644 --- a/src/perfect/bufferedFile.h +++ b/src/perfect/bufferedFile.h @@ -1,9 +1,9 @@ /*********************************************************************\ - bufferedFile.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + bufferedFile.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef BUFFERED_FILE_H @@ -20,35 +20,35 @@ using namespace std; class BufferedFile { private: - // Variables - HANDLE hFile; // Handle of the file - unsigned int numThreads; // number of threads - unsigned char *readBuffer; // Array of size [numThreads*blockSize] containing the data of the block, where reading is taking place - unsigned char *writeBuffer; // '' - access by [threadNo*bufferSize+position] - long long *curReadingPointer; // array of size [numThreads] with pointers to the byte which is currently read - long long *curWritingPointer; // '' - unsigned int *bytesInReadBuffer; // - unsigned int *bytesInWriteBuffer; // - unsigned int bufferSize; // size in bytes of a buffer - long long fileSize; // size in bytes - CRITICAL_SECTION csIO; + // Variables + HANDLE hFile; // Handle of the file + unsigned int numThreads; // number of threads + unsigned char *readBuffer; // Array of size [numThreads*blockSize] containing the data of the block, where reading is taking place + unsigned char *writeBuffer; // '' - access by [threadNo*bufferSize+position] + long long *curReadingPointer; // array of size [numThreads] with pointers to the byte which is currently read + long long *curWritingPointer; // '' + unsigned int *bytesInReadBuffer; // + unsigned int *bytesInWriteBuffer; // + unsigned int bufferSize; // size in bytes of a buffer + long long fileSize; // size in bytes + CRITICAL_SECTION csIO; - // Functions - void writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); - void readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); + // Functions + void writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); + void readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); public: - // Constructor / destructor - BufferedFile(unsigned int numThreads, unsigned int bufferSizeInBytes, const char *fileName); - ~BufferedFile(); + // Constructor / destructor + BufferedFile(unsigned int numThreads, unsigned int bufferSizeInBytes, const char *fileName); + ~BufferedFile(); - // Functions - bool flushBuffers(); - bool writeBytes(unsigned int numBytes, unsigned char *pData); - bool readBytes(unsigned int numBytes, unsigned char *pData); - bool writeBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData); - bool readBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData); - long long getFileSize(); + // Functions + bool flushBuffers(); + bool writeBytes(unsigned int numBytes, unsigned char *pData); + bool readBytes(unsigned int numBytes, unsigned char *pData); + bool writeBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData); + bool readBytes(unsigned int threadNo, long long positionInFile, unsigned int numBytes, unsigned char *pData); + long long getFileSize(); }; #endif diff --git a/src/perfect/config.h b/src/perfect/config.h index 8559a866..3dfc541e 100644 --- a/src/perfect/config.h +++ b/src/perfect/config.h @@ -1,9 +1,9 @@ /*********************************************************************\ - config.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + config.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef CONFIG_H diff --git a/src/perfect/cyclicArray.cpp b/src/perfect/cyclicArray.cpp index eade6bb5..9eae6953 100644 --- a/src/perfect/cyclicArray.cpp +++ b/src/perfect/cyclicArray.cpp @@ -1,9 +1,9 @@ /********************************************************************* - CyclicArray.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + CyclicArray.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "cyclicArray.h" @@ -14,26 +14,25 @@ //-----------------------------F------------------------------------------------ CyclicArray::CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlocks, const char *fileName) { - // Init blocks - blockSize = blockSizeInBytes; - numBlocks = numberOfBlocks; - readingBlock = new unsigned char[blockSize]; - writingBlock = new unsigned char[blockSize]; - curReadingPointer = writingBlock; - curWritingPointer = writingBlock; - readWriteInSameRound = true; - curReadingBlock = 0; - curWritingBlock = 0; + // Init blocks + blockSize = blockSizeInBytes; + numBlocks = numberOfBlocks; + readingBlock = new unsigned char[blockSize]; + writingBlock = new unsigned char[blockSize]; + curReadingPointer = writingBlock; + curWritingPointer = writingBlock; + readWriteInSameRound = true; + curReadingBlock = 0; + curWritingBlock = 0; - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - // opened file succesfully - if (hFile == INVALID_HANDLE_VALUE) - { - hFile = nullptr; - return; - } + // opened file succesfully + if (hFile == INVALID_HANDLE_VALUE) { + hFile = nullptr; + return; + } } //----------------------------------------------------------------------------- @@ -42,13 +41,13 @@ CyclicArray::CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlo //----------------------------------------------------------------------------- CyclicArray::~CyclicArray() { - // delete arrays - delete[] readingBlock; - delete[] writingBlock; + // delete arrays + delete[] readingBlock; + delete[] writingBlock; - // close file - if (hFile != nullptr) - CloseHandle(hFile); + // close file + if (hFile != nullptr) + CloseHandle(hFile); } //----------------------------------------------------------------------------- @@ -57,32 +56,28 @@ CyclicArray::~CyclicArray() //----------------------------------------------------------------------------- void CyclicArray::writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData) { - DWORD dwBytesWritten; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = sizeInBytes; + DWORD dwBytesWritten; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = sizeInBytes; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - cout << endl - << "SetFilePointerEx failed!"; + while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) + cout << endl + << "SetFilePointerEx failed!"; - while (restingBytes > 0) - { - if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) - { - restingBytes -= dwBytesWritten; - pData = (void *)(((unsigned char *)pData) + dwBytesWritten); - if (restingBytes > 0) - cout << endl - << "Still " << restingBytes << " to write!"; - } - else - { - cout << endl - << "WriteFile Failed!"; - } - } + while (restingBytes > 0) { + if (WriteFile(hFile, pData, sizeInBytes, &dwBytesWritten, nullptr) == TRUE) { + restingBytes -= dwBytesWritten; + pData = (void *)(((unsigned char *)pData) + dwBytesWritten); + if (restingBytes > 0) + cout << endl + << "Still " << restingBytes << " to write!"; + } else { + cout << endl + << "WriteFile Failed!"; + } + } } //----------------------------------------------------------------------------- @@ -91,32 +86,28 @@ void CyclicArray::writeDataToFile(HANDLE hFile, long long offset, unsigned int s //----------------------------------------------------------------------------- void CyclicArray::readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData) { - DWORD dwBytesRead; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = sizeInBytes; + DWORD dwBytesRead; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = sizeInBytes; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - cout << endl - << "SetFilePointerEx failed!"; + while (!SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) + cout << endl + << "SetFilePointerEx failed!"; - while (restingBytes > 0) - { - if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) - { - restingBytes -= dwBytesRead; - pData = (void *)(((unsigned char *)pData) + dwBytesRead); - if (restingBytes > 0) - cout << endl - << "Still " << restingBytes << " to read!"; - } - else - { - cout << endl - << "ReadFile Failed!"; - } - } + while (restingBytes > 0) { + if (ReadFile(hFile, pData, sizeInBytes, &dwBytesRead, nullptr) == TRUE) { + restingBytes -= dwBytesRead; + pData = (void *)(((unsigned char *)pData) + dwBytesRead); + if (restingBytes > 0) + cout << endl + << "Still " << restingBytes << " to read!"; + } else { + cout << endl + << "ReadFile Failed!"; + } + } } //----------------------------------------------------------------------------- @@ -126,47 +117,44 @@ void CyclicArray::readDataFromFile(HANDLE hFile, long long offset, unsigned int //----------------------------------------------------------------------------- bool CyclicArray::addBytes(unsigned int numBytes, unsigned char *pData) { - // locals - unsigned int bytesWritten = 0; + // locals + unsigned int bytesWritten = 0; - // write each byte - while (bytesWritten < numBytes) - { + // write each byte + while (bytesWritten < numBytes) { - // store byte in current reading block - *curWritingPointer = *pData; - curWritingPointer++; - bytesWritten++; - pData++; + // store byte in current reading block + *curWritingPointer = *pData; + curWritingPointer++; + bytesWritten++; + pData++; - // when block is full then save current one to file and begin new one - if (curWritingPointer == writingBlock + blockSize) - { + // when block is full then save current one to file and begin new one + if (curWritingPointer == writingBlock + blockSize) { - // copy data into reading block? - if (curReadingBlock == curWritingBlock) - { - memcpy(readingBlock, writingBlock, blockSize); - curReadingPointer = readingBlock + (curReadingPointer - writingBlock); - } + // copy data into reading block? + if (curReadingBlock == curWritingBlock) { + memcpy(readingBlock, writingBlock, blockSize); + curReadingPointer = readingBlock + (curReadingPointer - writingBlock); + } - // will reading block be overwritten? - if (curReadingBlock == curWritingBlock && !readWriteInSameRound) - return false; + // will reading block be overwritten? + if (curReadingBlock == curWritingBlock && !readWriteInSameRound) + return false; - // store bock in file - writeDataToFile(hFile, ((long long)blockSize) * ((long long)curWritingBlock), blockSize, writingBlock); + // store bock in file + writeDataToFile(hFile, ((long long)blockSize) * ((long long)curWritingBlock), blockSize, writingBlock); - // set pointer to beginnig of writing block - curWritingPointer = writingBlock; - curWritingBlock = (curWritingBlock + 1) % numBlocks; - if (curWritingBlock == 0) - readWriteInSameRound = false; - } - } + // set pointer to beginnig of writing block + curWritingPointer = writingBlock; + curWritingBlock = (curWritingBlock + 1) % numBlocks; + if (curWritingBlock == 0) + readWriteInSameRound = false; + } + } - // everything ok - return true; + // everything ok + return true; } //----------------------------------------------------------------------------- @@ -175,10 +163,10 @@ bool CyclicArray::addBytes(unsigned int numBytes, unsigned char *pData) //----------------------------------------------------------------------------- bool CyclicArray::bytesAvailable() { - if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound) - return false; - else - return true; + if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound) + return false; + else + return true; } //----------------------------------------------------------------------------- @@ -188,51 +176,46 @@ bool CyclicArray::bytesAvailable() //----------------------------------------------------------------------------- bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData) { - // locals - unsigned int bytesRead = 0; + // locals + unsigned int bytesRead = 0; - // read each byte - while (bytesRead < numBytes) - { + // read each byte + while (bytesRead < numBytes) { - // was current reading byte already written ? - if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound) - return false; + // was current reading byte already written ? + if (curReadingBlock == curWritingBlock && curReadingPointer == curWritingPointer && readWriteInSameRound) + return false; - // read current byte - *pData = *curReadingPointer; - curReadingPointer++; - bytesRead++; - pData++; + // read current byte + *pData = *curReadingPointer; + curReadingPointer++; + bytesRead++; + pData++; - // load next block? - if (curReadingPointer == readingBlock + blockSize) - { + // load next block? + if (curReadingPointer == readingBlock + blockSize) { - // go to next block - curReadingBlock = (curReadingBlock + 1) % numBlocks; - if (curReadingBlock == 0) - readWriteInSameRound = true; + // go to next block + curReadingBlock = (curReadingBlock + 1) % numBlocks; + if (curReadingBlock == 0) + readWriteInSameRound = true; - // writing block reached ? - if (curReadingBlock == curWritingBlock) - { - curReadingPointer = writingBlock; - } - else - { + // writing block reached ? + if (curReadingBlock == curWritingBlock) { + curReadingPointer = writingBlock; + } else { - // set pointer to beginnig of reading block - curReadingPointer = readingBlock; + // set pointer to beginnig of reading block + curReadingPointer = readingBlock; - // read whole block from file - readDataFromFile(hFile, ((long long)blockSize) * ((long long)curReadingBlock), blockSize, readingBlock); - } - } - } + // read whole block from file + readDataFromFile(hFile, ((long long)blockSize) * ((long long)curReadingBlock), blockSize, readingBlock); + } + } + } - // everything ok - return true; + // everything ok + return true; } //----------------------------------------------------------------------------- @@ -242,71 +225,68 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData) //----------------------------------------------------------------------------- bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded) { - // locals - HANDLE hLoadFile; - unsigned char *dataInFile; - LARGE_INTEGER largeInt; - LONGLONG maxFileSize = ((LONGLONG)blockSize) * ((LONGLONG)numBlocks); - LONGLONG curOffset = 0; - unsigned int numBlocksInFile; - unsigned int curBlock; - unsigned int numBytesInLastBlock; - numBytesLoaded = 0; + // locals + HANDLE hLoadFile; + unsigned char *dataInFile; + LARGE_INTEGER largeInt; + LONGLONG maxFileSize = ((LONGLONG)blockSize) * ((LONGLONG)numBlocks); + LONGLONG curOffset = 0; + unsigned int numBlocksInFile; + unsigned int curBlock; + unsigned int numBytesInLastBlock; + numBytesLoaded = 0; - // cyclic array file must be open - if (hFile == nullptr) - return false; + // cyclic array file must be open + if (hFile == nullptr) + return false; - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hLoadFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + hLoadFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - // opened file succesfully - if (hLoadFile == INVALID_HANDLE_VALUE) - { - return false; - } + // opened file succesfully + if (hLoadFile == INVALID_HANDLE_VALUE) { + return false; + } - // does data of file fit into cyclic array ? - GetFileSizeEx(hLoadFile, &largeInt); + // does data of file fit into cyclic array ? + GetFileSizeEx(hLoadFile, &largeInt); - if (maxFileSize < largeInt.QuadPart) - { - CloseHandle(hLoadFile); - return false; - } + if (maxFileSize < largeInt.QuadPart) { + CloseHandle(hLoadFile); + return false; + } - // reset - curReadingPointer = writingBlock; - curWritingPointer = writingBlock; - readWriteInSameRound = true; - curReadingBlock = 0; - curWritingBlock = 0; + // reset + curReadingPointer = writingBlock; + curWritingPointer = writingBlock; + readWriteInSameRound = true; + curReadingBlock = 0; + curWritingBlock = 0; - numBlocksInFile = (unsigned int)(largeInt.QuadPart / ((LONGLONG)blockSize)) + 1; - numBytesInLastBlock = (unsigned int)(largeInt.QuadPart % ((LONGLONG)blockSize)); - dataInFile = new unsigned char[blockSize]; + numBlocksInFile = (unsigned int)(largeInt.QuadPart / ((LONGLONG)blockSize)) + 1; + numBytesInLastBlock = (unsigned int)(largeInt.QuadPart % ((LONGLONG)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 - readDataFromFile(hLoadFile, curOffset, blockSize, dataInFile); + // load data from file + readDataFromFile(hLoadFile, curOffset, blockSize, dataInFile); - // put block in cyclic array - addBytes(blockSize, dataInFile); - } + // put block in cyclic array + addBytes(blockSize, dataInFile); + } - // last block - readDataFromFile(hLoadFile, curOffset, numBytesInLastBlock, dataInFile); - addBytes(numBytesInLastBlock, dataInFile); - curOffset += numBytesInLastBlock; - numBytesLoaded = curOffset; + // last block + readDataFromFile(hLoadFile, curOffset, numBytesInLastBlock, dataInFile); + addBytes(numBytesInLastBlock, dataInFile); + curOffset += numBytesInLastBlock; + numBytesLoaded = curOffset; - // everything ok - delete[] dataInFile; - CloseHandle(hLoadFile); - return true; + // everything ok + delete[] dataInFile; + CloseHandle(hLoadFile); + return true; } //----------------------------------------------------------------------------- @@ -316,74 +296,64 @@ bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded) //----------------------------------------------------------------------------- bool CyclicArray::saveFile(const char *fileName) { - // locals - unsigned char *dataInFile; - HANDLE hSaveFile; - LONGLONG curOffset; - unsigned int curBlock; - unsigned int bytesToWrite; - void *pointer; + // locals + unsigned char *dataInFile; + HANDLE hSaveFile; + LONGLONG curOffset; + unsigned int curBlock; + unsigned int bytesToWrite; + void *pointer; - // cyclic array file must be open - if (hFile == nullptr) - { - return false; - } + // cyclic array file must be open + if (hFile == nullptr) { + return false; + } - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hSaveFile = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + hSaveFile = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - // opened file succesfully - if (hSaveFile == INVALID_HANDLE_VALUE) - { - return false; - } + // opened file succesfully + if (hSaveFile == INVALID_HANDLE_VALUE) { + return false; + } - // alloc mem - curOffset = 0; - curBlock = curReadingBlock; - dataInFile = new unsigned char[blockSize]; + // alloc mem + curOffset = 0; + curBlock = curReadingBlock; + dataInFile = new unsigned char[blockSize]; - do - { + do { - // copy current block - if (curBlock == curWritingBlock && curBlock == curReadingBlock) - { - pointer = curReadingPointer; - bytesToWrite = (unsigned int)(curWritingPointer - curReadingPointer); - } - else if (curBlock == curWritingBlock) - { - pointer = writingBlock; - bytesToWrite = (unsigned int)(curWritingPointer - writingBlock); - } - else if (curBlock == curReadingBlock) - { - pointer = curReadingPointer; - bytesToWrite = blockSize - (unsigned int)(curReadingPointer - readingBlock); - } - else - { - readDataFromFile(hFile, ((long long)curBlock) * ((long long)blockSize), blockSize, dataInFile); - pointer = dataInFile; - bytesToWrite = blockSize; - } + // copy current block + if (curBlock == curWritingBlock && curBlock == curReadingBlock) { + pointer = curReadingPointer; + bytesToWrite = (unsigned int)(curWritingPointer - curReadingPointer); + } else if (curBlock == curWritingBlock) { + pointer = writingBlock; + bytesToWrite = (unsigned int)(curWritingPointer - writingBlock); + } else if (curBlock == curReadingBlock) { + pointer = curReadingPointer; + bytesToWrite = blockSize - (unsigned int)(curReadingPointer - readingBlock); + } else { + readDataFromFile(hFile, ((long long)curBlock) * ((long long)blockSize), blockSize, dataInFile); + pointer = dataInFile; + bytesToWrite = blockSize; + } - // save data to file - writeDataToFile(hSaveFile, curOffset, bytesToWrite, pointer); - curOffset += bytesToWrite; + // save data to file + writeDataToFile(hSaveFile, curOffset, bytesToWrite, pointer); + curOffset += bytesToWrite; - // exit? - if (curBlock == curWritingBlock) - break; - else - curBlock = (curBlock + 1) % numBlocks; + // exit? + if (curBlock == curWritingBlock) + break; + else + curBlock = (curBlock + 1) % numBlocks; - } while (true); + } while (true); - // everything ok - delete[] dataInFile; - CloseHandle(hSaveFile); - return true; + // everything ok + delete[] dataInFile; + CloseHandle(hSaveFile); + return true; } \ No newline at end of file diff --git a/src/perfect/cyclicArray.h b/src/perfect/cyclicArray.h index 55fa1cfc..c9aefa3f 100644 --- a/src/perfect/cyclicArray.h +++ b/src/perfect/cyclicArray.h @@ -1,9 +1,9 @@ /*********************************************************************\ - CyclicArray.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + CyclicArray.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef CYLCIC_ARRAY_H @@ -20,33 +20,33 @@ using namespace std; class CyclicArray { private: - // Variables - HANDLE hFile; // Handle of the file - unsigned char *readingBlock; // Array of size [blockSize] containing the data of the block, where reading is taking place - unsigned char *writingBlock; // '' - unsigned char *curReadingPointer; // pointer to the byte which is currently read - unsigned char *curWritingPointer; // '' - unsigned int blockSize; // size in bytes of a block - unsigned int curReadingBlock; // index of the block, where reading is taking place - unsigned int curWritingBlock; // index of the block, where writing is taking place - unsigned int numBlocks; // amount of blocks - bool readWriteInSameRound; // true if curReadingBlock > curWritingBlock, false otherwise + // Variables + HANDLE hFile; // Handle of the file + unsigned char *readingBlock; // Array of size [blockSize] containing the data of the block, where reading is taking place + unsigned char *writingBlock; // '' + unsigned char *curReadingPointer; // pointer to the byte which is currently read + unsigned char *curWritingPointer; // '' + unsigned int blockSize; // size in bytes of a block + unsigned int curReadingBlock; // index of the block, where reading is taking place + unsigned int curWritingBlock; // index of the block, where writing is taking place + unsigned int numBlocks; // amount of blocks + bool readWriteInSameRound; // true if curReadingBlock > curWritingBlock, false otherwise - // Functions - void writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); - void readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); + // Functions + void writeDataToFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); + void readDataFromFile(HANDLE hFile, long long offset, unsigned int sizeInBytes, void *pData); public: - // Constructor / destructor - CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlocks, const char *fileName); - ~CyclicArray(); + // Constructor / destructor + CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlocks, const char *fileName); + ~CyclicArray(); - // Functions - bool addBytes(unsigned int numBytes, unsigned char *pData); - bool takeBytes(unsigned int numBytes, unsigned char *pData); - bool loadFile(const char *fileName, LONGLONG &numBytesLoaded); - bool saveFile(const char *fileName); - bool bytesAvailable(); + // Functions + bool addBytes(unsigned int numBytes, unsigned char *pData); + bool takeBytes(unsigned int numBytes, unsigned char *pData); + bool loadFile(const char *fileName, LONGLONG &numBytesLoaded); + bool saveFile(const char *fileName); + bool bytesAvailable(); }; #endif diff --git a/src/perfect/main.cpp b/src/perfect/main.cpp index 117a2600..7dc116f0 100644 --- a/src/perfect/main.cpp +++ b/src/perfect/main.cpp @@ -36,7 +36,7 @@ int main(void) cout << "*************************" << endl; cout << "* Muehle *" << endl; cout << "*************************" << endl - << endl; + << endl; ai->setDatabasePath(databaseDirectory); @@ -47,23 +47,20 @@ int main(void) pos->beginNewGame(ai, ai, (rand() % 2) ? fieldStruct::playerOne : fieldStruct::playerTwo); #endif // SELF_PLAY - if (calculateDatabase) - { + if (calculateDatabase) { // calculate ai->calculateDatabase(MAX_DEPTH_OF_TREE, false); // test database cout << endl - << "Begin test starting from layer: "; + << "Begin test starting from layer: "; startTestFromLayer; cout << endl - << "End test at layer: "; + << "End test at layer: "; endTestAtLayer; ai->testLayers(startTestFromLayer, endTestAtLayer); - } - else - { + } else { #ifdef SELF_PLAY int moveCount = 0; @@ -79,8 +76,7 @@ int main(void) #endif // SELF_PLAY // play - do - { + do { // print board cout << "\n\n\n\n\n\n\n\n\n\n\n"; pos->getComputersChoice(&pushFrom, &pushTo); @@ -89,8 +85,7 @@ int main(void) #ifdef SELF_PLAY moveCount++; - if (moveCount > 99) - { + if (moveCount > 99) { goto out; } #endif // SELF_PLAY @@ -98,10 +93,8 @@ int main(void) pos->printBoard(); // Human - if ((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman)) - { - do - { + if ((pos->getCurrentPlayer() == fieldStruct::playerOne && playerOneHuman) || (pos->getCurrentPlayer() == fieldStruct::playerTwo && playerTwoHuman)) { + do { // Show text if (pos->mustStoneBeRemoved()) cout << "\n Which stone do you want to remove? [a-x]: \n\n\n"; @@ -117,15 +110,12 @@ int main(void) else pushFrom = fieldStruct::size; - if (pos->inSettingPhase()) - { + if (pos->inSettingPhase()) { if ((ch[0] >= 'a') && (ch[0] <= 'x')) pushTo = ch[0] - 'a'; else pushTo = fieldStruct::size; - } - else - { + } else { if ((ch[1] >= 'a') && (ch[1] <= 'x')) pushTo = ch[1] - 'a'; else @@ -133,12 +123,10 @@ int main(void) } // 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 - do - { + do { pos->undo_move(); } 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); // Computer - } - else - { + } else { cout << "\n"; pos->do_move(pushFrom, pushTo); } diff --git a/src/perfect/millAI.cpp b/src/perfect/millAI.cpp index 31932dba..d8145ea6 100644 --- a/src/perfect/millAI.cpp +++ b/src/perfect/millAI.cpp @@ -1,9 +1,9 @@ /********************************************************************* - millAI.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + millAI.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "millAI.h" @@ -16,42 +16,42 @@ using namespace std; //----------------------------------------------------------------------------- void fieldStruct::printBoard() { - // locals - unsigned int index; - char c[fieldStruct::size]; + // locals + unsigned int index; + char c[fieldStruct::size]; - for (index = 0; index < fieldStruct::size; index++) - c[index] = GetCharFromStone(this->board[index]); + for (index = 0; index < fieldStruct::size; index++) + c[index] = GetCharFromStone(this->board[index]); - cout << "current player : " << GetCharFromStone(this->curPlayer->id) << " has " << this->curPlayer->numStones << " stones\n"; - cout << "opponent player : " << GetCharFromStone(this->oppPlayer->id) << " has " << this->oppPlayer->numStones << " stones\n"; - cout << "Num Stones to be removed: " << this->stoneMustBeRemoved << "\n"; - cout << "setting phase : " << (this->settingPhase ? "true" : "false"); - cout << "\n"; - cout << "\n a-----b-----c " << c[0] << "-----" << c[1] << "-----" << c[2]; - cout << "\n | | | " - << "| | |"; - cout << "\n | d---e---f | " - << "| " << c[3] << "---" << c[4] << "---" << c[5] << " |"; - cout << "\n | | | | | " - << "| | | | |"; - cout << "\n | | g-h-i | | " - << "| | " << c[6] << "-" << c[7] << "-" << c[8] << " | |"; - cout << "\n | | | | | | | " - << "| | | | | |"; - cout << "\n j-k-l m-n-o " << c[9] << "-" << c[10] << "-" << c[11] << " " << c[12] << "-" << c[13] << "-" << c[14]; - cout << "\n | | | | | | | " - << "| | | | | |"; - cout << "\n | | p-q-r | | " - << "| | " << c[15] << "-" << c[16] << "-" << c[17] << " | |"; - cout << "\n | | | | | " - << "| | | | |"; - cout << "\n | s---t---u | " - << "| " << c[18] << "---" << c[19] << "---" << c[20] << " |"; - cout << "\n | | | " - << "| | |"; - cout << "\n v-----w-----x " << c[21] << "-----" << c[22] << "-----" << c[23]; - cout << "\n"; + cout << "current player : " << GetCharFromStone(this->curPlayer->id) << " has " << this->curPlayer->numStones << " stones\n"; + cout << "opponent player : " << GetCharFromStone(this->oppPlayer->id) << " has " << this->oppPlayer->numStones << " stones\n"; + cout << "Num Stones to be removed: " << this->stoneMustBeRemoved << "\n"; + cout << "setting phase : " << (this->settingPhase ? "true" : "false"); + cout << "\n"; + cout << "\n a-----b-----c " << c[0] << "-----" << c[1] << "-----" << c[2]; + cout << "\n | | | " + << "| | |"; + cout << "\n | d---e---f | " + << "| " << c[3] << "---" << c[4] << "---" << c[5] << " |"; + cout << "\n | | | | | " + << "| | | | |"; + cout << "\n | | g-h-i | | " + << "| | " << c[6] << "-" << c[7] << "-" << c[8] << " | |"; + cout << "\n | | | | | | | " + << "| | | | | |"; + cout << "\n j-k-l m-n-o " << c[9] << "-" << c[10] << "-" << c[11] << " " << c[12] << "-" << c[13] << "-" << c[14]; + cout << "\n | | | | | | | " + << "| | | | | |"; + cout << "\n | | p-q-r | | " + << "| | " << c[15] << "-" << c[16] << "-" << c[17] << " | |"; + cout << "\n | | | | | " + << "| | | | |"; + cout << "\n | s---t---u | " + << "| " << c[18] << "---" << c[19] << "---" << c[20] << " |"; + cout << "\n | | | " + << "| | |"; + cout << "\n v-----w-----x " << c[21] << "-----" << c[22] << "-----" << c[23]; + cout << "\n"; } //----------------------------------------------------------------------------- @@ -60,22 +60,21 @@ void fieldStruct::printBoard() //----------------------------------------------------------------------------- char fieldStruct::GetCharFromStone(int stone) { - switch (stone) - { - case fieldStruct::playerOne: - return 'o'; - case fieldStruct::playerTwo: - return 'x'; - case fieldStruct::playerOneWarning: - return '1'; - case fieldStruct::playerTwoWarning: - return '2'; - case fieldStruct::playerBothWarning: - return '3'; - case fieldStruct::squareIsFree: - return ' '; - } - return 'f'; + switch (stone) { + case fieldStruct::playerOne: + return 'o'; + case fieldStruct::playerTwo: + return 'x'; + case fieldStruct::playerOneWarning: + return '1'; + case fieldStruct::playerTwoWarning: + return '2'; + case fieldStruct::playerBothWarning: + return '3'; + case fieldStruct::squareIsFree: + return ' '; + } + return 'f'; } //----------------------------------------------------------------------------- @@ -84,30 +83,28 @@ char fieldStruct::GetCharFromStone(int stone) //----------------------------------------------------------------------------- void fieldStruct::copyBoard(fieldStruct *destination) { - unsigned int i, j; + unsigned int i, j; - this->curPlayer->copyPlayer(destination->curPlayer); - this->oppPlayer->copyPlayer(destination->oppPlayer); + this->curPlayer->copyPlayer(destination->curPlayer); + this->oppPlayer->copyPlayer(destination->oppPlayer); - destination->stonesSet = this->stonesSet; - destination->settingPhase = this->settingPhase; - destination->stoneMustBeRemoved = this->stoneMustBeRemoved; + destination->stonesSet = this->stonesSet; + destination->settingPhase = this->settingPhase; + 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->warnings[i] = this->warnings[i]; - destination->stonePartOfMill[i] = this->stonePartOfMill[i]; + destination->board[i] = this->board[i]; + destination->warnings[i] = this->warnings[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->stoneMoveAble[i][j] = this->stoneMoveAble[i][j]; - destination->neighbour[i][j / 2][j % 2] = this->neighbour[i][j / 2][j % 2]; - } - } + destination->connectedSquare[i][j] = this->connectedSquare[i][j]; + destination->stoneMoveAble[i][j] = this->stoneMoveAble[i][j]; + destination->neighbour[i][j / 2][j % 2] = this->neighbour[i][j / 2][j % 2]; + } + } } //----------------------------------------------------------------------------- @@ -116,18 +113,18 @@ void fieldStruct::copyBoard(fieldStruct *destination) //----------------------------------------------------------------------------- void Player::copyPlayer(Player *destination) { - unsigned int i; + unsigned int i; - destination->numStonesMissing = this->numStonesMissing; - destination->numStones = this->numStones; - destination->id = this->id; - destination->warning = this->warning; - destination->numPossibleMoves = this->numPossibleMoves; + destination->numStonesMissing = this->numStonesMissing; + destination->numStones = this->numStones; + destination->id = this->id; + destination->warning = this->warning; + destination->numPossibleMoves = this->numPossibleMoves; - for (i = 0; i < MAX_NUM_POS_MOVES; i++) - destination->posFrom[i] = this->posFrom[i]; - for (i = 0; i < MAX_NUM_POS_MOVES; i++) - destination->posTo[i] = this->posTo[i]; + for (i = 0; i < MAX_NUM_POS_MOVES; i++) + destination->posFrom[i] = this->posFrom[i]; + for (i = 0; i < MAX_NUM_POS_MOVES; i++) + destination->posTo[i] = this->posTo[i]; } //----------------------------------------------------------------------------- @@ -136,91 +133,90 @@ void Player::copyPlayer(Player *destination) //----------------------------------------------------------------------------- void fieldStruct::createBoard() { - // locals - unsigned int i; + // locals + unsigned int i; - curPlayer = new Player; - oppPlayer = new Player; + curPlayer = new Player; + oppPlayer = new Player; - curPlayer->id = playerOne; - stonesSet = 0; - stoneMustBeRemoved = 0; - settingPhase = true; - curPlayer->warning = (curPlayer->id == playerOne) ? playerOneWarning : playerTwoWarning; - oppPlayer->id = (curPlayer->id == playerOne) ? playerTwo : playerOne; - oppPlayer->warning = (curPlayer->id == playerOne) ? playerTwoWarning : playerOneWarning; - curPlayer->numStones = 0; - oppPlayer->numStones = 0; - curPlayer->numPossibleMoves = 0; - oppPlayer->numPossibleMoves = 0; - curPlayer->numStonesMissing = 0; - oppPlayer->numStonesMissing = 0; + curPlayer->id = playerOne; + stonesSet = 0; + stoneMustBeRemoved = 0; + settingPhase = true; + curPlayer->warning = (curPlayer->id == playerOne) ? playerOneWarning : playerTwoWarning; + oppPlayer->id = (curPlayer->id == playerOne) ? playerTwo : playerOne; + oppPlayer->warning = (curPlayer->id == playerOne) ? playerTwoWarning : playerOneWarning; + curPlayer->numStones = 0; + oppPlayer->numStones = 0; + curPlayer->numPossibleMoves = 0; + oppPlayer->numPossibleMoves = 0; + curPlayer->numStonesMissing = 0; + oppPlayer->numStonesMissing = 0; - // zero - for (i = 0; i < size; i++) - { - board[i] = squareIsFree; - warnings[i] = noWarning; - stonePartOfMill[i] = 0; - stoneMoveAble[i][0] = false; - stoneMoveAble[i][1] = false; - stoneMoveAble[i][2] = false; - stoneMoveAble[i][3] = false; - } + // zero + for (i = 0; i < size; i++) { + board[i] = squareIsFree; + warnings[i] = noWarning; + stonePartOfMill[i] = 0; + stoneMoveAble[i][0] = false; + stoneMoveAble[i][1] = false; + stoneMoveAble[i][2] = false; + stoneMoveAble[i][3] = false; + } - // set connections - i = size; + // set connections + i = size; - setConnection(0, 1, 9, i, i); - setConnection(1, 2, 4, 0, i); - setConnection(2, i, 14, 1, i); - setConnection(3, 4, 10, i, i); - setConnection(4, 5, 7, 3, 1); - setConnection(5, i, 13, 4, i); - setConnection(6, 7, 11, i, i); - setConnection(7, 8, i, 6, 4); - setConnection(8, i, 12, 7, i); - setConnection(9, 10, 21, i, 0); - setConnection(10, 11, 18, 9, 3); - setConnection(11, i, 15, 10, 6); - setConnection(12, 13, 17, i, 8); - setConnection(13, 14, 20, 12, 5); - setConnection(14, i, 23, 13, 2); - setConnection(15, 16, i, i, 11); - setConnection(16, 17, 19, 15, i); - setConnection(17, i, i, 16, 12); - setConnection(18, 19, i, i, 10); - setConnection(19, 20, 22, 18, 16); - setConnection(20, i, i, 19, 13); - setConnection(21, 22, i, i, 9); - setConnection(22, 23, i, 21, 19); - setConnection(23, i, i, 22, 14); + setConnection(0, 1, 9, i, i); + setConnection(1, 2, 4, 0, i); + setConnection(2, i, 14, 1, i); + setConnection(3, 4, 10, i, i); + setConnection(4, 5, 7, 3, 1); + setConnection(5, i, 13, 4, i); + setConnection(6, 7, 11, i, i); + setConnection(7, 8, i, 6, 4); + setConnection(8, i, 12, 7, i); + setConnection(9, 10, 21, i, 0); + setConnection(10, 11, 18, 9, 3); + setConnection(11, i, 15, 10, 6); + setConnection(12, 13, 17, i, 8); + setConnection(13, 14, 20, 12, 5); + setConnection(14, i, 23, 13, 2); + setConnection(15, 16, i, i, 11); + setConnection(16, 17, 19, 15, i); + setConnection(17, i, i, 16, 12); + setConnection(18, 19, i, i, 10); + setConnection(19, 20, 22, 18, 16); + setConnection(20, i, i, 19, 13); + setConnection(21, 22, i, i, 9); + setConnection(22, 23, i, 21, 19); + setConnection(23, i, i, 22, 14); - // neighbours - setNeighbour(0, 1, 2, 9, 21); - setNeighbour(1, 0, 2, 4, 7); - setNeighbour(2, 0, 1, 14, 23); - setNeighbour(3, 4, 5, 10, 18); - setNeighbour(4, 1, 7, 3, 5); - setNeighbour(5, 3, 4, 13, 20); - setNeighbour(6, 7, 8, 11, 15); - setNeighbour(7, 1, 4, 6, 8); - setNeighbour(8, 6, 7, 12, 17); - setNeighbour(9, 10, 11, 0, 21); - setNeighbour(10, 9, 11, 3, 18); - setNeighbour(11, 9, 10, 6, 15); - setNeighbour(12, 13, 14, 8, 17); - setNeighbour(13, 12, 14, 5, 20); - setNeighbour(14, 12, 13, 2, 23); - setNeighbour(15, 6, 11, 16, 17); - setNeighbour(16, 15, 17, 19, 22); - setNeighbour(17, 15, 16, 8, 12); - setNeighbour(18, 3, 10, 19, 20); - setNeighbour(19, 18, 20, 16, 22); - setNeighbour(20, 5, 13, 18, 19); - setNeighbour(21, 0, 9, 22, 23); - setNeighbour(22, 16, 19, 21, 23); - setNeighbour(23, 2, 14, 21, 22); + // neighbours + setNeighbour(0, 1, 2, 9, 21); + setNeighbour(1, 0, 2, 4, 7); + setNeighbour(2, 0, 1, 14, 23); + setNeighbour(3, 4, 5, 10, 18); + setNeighbour(4, 1, 7, 3, 5); + setNeighbour(5, 3, 4, 13, 20); + setNeighbour(6, 7, 8, 11, 15); + setNeighbour(7, 1, 4, 6, 8); + setNeighbour(8, 6, 7, 12, 17); + setNeighbour(9, 10, 11, 0, 21); + setNeighbour(10, 9, 11, 3, 18); + setNeighbour(11, 9, 10, 6, 15); + setNeighbour(12, 13, 14, 8, 17); + setNeighbour(13, 12, 14, 5, 20); + setNeighbour(14, 12, 13, 2, 23); + setNeighbour(15, 6, 11, 16, 17); + setNeighbour(16, 15, 17, 19, 22); + setNeighbour(17, 15, 16, 8, 12); + setNeighbour(18, 3, 10, 19, 20); + setNeighbour(19, 18, 20, 16, 22); + setNeighbour(20, 5, 13, 18, 19); + setNeighbour(21, 0, 9, 22, 23); + setNeighbour(22, 16, 19, 21, 23); + setNeighbour(23, 2, 14, 21, 22); } //----------------------------------------------------------------------------- @@ -229,8 +225,8 @@ void fieldStruct::createBoard() //----------------------------------------------------------------------------- void fieldStruct::deleteBoard() { - SAFE_DELETE(curPlayer); - SAFE_DELETE(oppPlayer); + SAFE_DELETE(curPlayer); + SAFE_DELETE(oppPlayer); } //----------------------------------------------------------------------------- @@ -239,10 +235,10 @@ void fieldStruct::deleteBoard() //----------------------------------------------------------------------------- inline void fieldStruct::setConnection(unsigned int index, int firstDirection, int secondDirection, int thirdDirection, int fourthDirection) { - connectedSquare[index][0] = firstDirection; - connectedSquare[index][1] = secondDirection; - connectedSquare[index][2] = thirdDirection; - connectedSquare[index][3] = fourthDirection; + connectedSquare[index][0] = firstDirection; + connectedSquare[index][1] = secondDirection; + connectedSquare[index][2] = thirdDirection; + connectedSquare[index][3] = fourthDirection; } //----------------------------------------------------------------------------- @@ -251,8 +247,8 @@ inline void fieldStruct::setConnection(unsigned int index, int firstDirection, i //----------------------------------------------------------------------------- inline void fieldStruct::setNeighbour(unsigned int index, unsigned int firstNeighbour0, unsigned int secondNeighbour0, unsigned int firstNeighbour1, unsigned int secondNeighbour1) { - neighbour[index][0][0] = firstNeighbour0; - neighbour[index][0][1] = secondNeighbour0; - neighbour[index][1][0] = firstNeighbour1; - neighbour[index][1][1] = secondNeighbour1; + neighbour[index][0][0] = firstNeighbour0; + neighbour[index][0][1] = secondNeighbour0; + neighbour[index][1][0] = firstNeighbour1; + neighbour[index][1][1] = secondNeighbour1; } \ No newline at end of file diff --git a/src/perfect/millAI.h b/src/perfect/millAI.h index c6d57256..e0e9a51a 100644 --- a/src/perfect/millAI.h +++ b/src/perfect/millAI.h @@ -1,9 +1,9 @@ /*********************************************************************\ - millAI.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + millAI.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef MUEHLE_AI_H @@ -30,77 +30,77 @@ class Player { public: - int id; // static - unsigned int warning; // static - unsigned int numStones; // number of stones of this player on the board - unsigned int numStonesMissing; // number of stones, which where stolen by the opponent - unsigned int numPossibleMoves; // amount of possible moves - unsigned int posTo[MAX_NUM_POS_MOVES]; // target board position of a possible move - unsigned int posFrom[MAX_NUM_POS_MOVES]; // source board position of a possible move + int id; // static + unsigned int warning; // static + unsigned int numStones; // number of stones of this player on the board + unsigned int numStonesMissing; // number of stones, which where stolen by the opponent + unsigned int numPossibleMoves; // amount of possible moves + unsigned int posTo[MAX_NUM_POS_MOVES]; // target board position of a possible move + unsigned int posFrom[MAX_NUM_POS_MOVES]; // source board position of a possible move - void copyPlayer(Player *destination); + void copyPlayer(Player *destination); }; class fieldStruct { public: - // constants - static const int squareIsFree = 0; // trivial - static const int playerOne = -1; // so rowOwner can be calculated easy - static const int playerTwo = 1; - static const int playerBlack = -1; // so rowOwner can be calculated easy - static const int playerWhite = 1; - static const unsigned int noWarning = 0; // so the bitwise or-operation can be applied, without interacting with playerOne & Two - static const unsigned int playerOneWarning = 2; - static const unsigned int playerTwoWarning = 4; - static const unsigned int playerBothWarning = 6; - static const unsigned int numStonesPerPlayer = 9; - static const unsigned int size = 24; // number of squares - static const int gameDrawn = 3; // only a nonzero value + // constants + static const int squareIsFree = 0; // trivial + static const int playerOne = -1; // so rowOwner can be calculated easy + static const int playerTwo = 1; + static const int playerBlack = -1; // so rowOwner can be calculated easy + static const int playerWhite = 1; + static const unsigned int noWarning = 0; // so the bitwise or-operation can be applied, without interacting with playerOne & Two + static const unsigned int playerOneWarning = 2; + static const unsigned int playerTwoWarning = 4; + static const unsigned int playerBothWarning = 6; + static const unsigned int numStonesPerPlayer = 9; + static const unsigned int size = 24; // number of squares + static const int gameDrawn = 3; // only a nonzero value - // variables - int board[size]; // one of the values above for each board position - unsigned int warnings[size]; // array containing the warnings for each board position - bool stoneMoveAble[size][4]; // true if stone can be moved in this direction - unsigned int stonePartOfMill[size]; // the number of mills, of which this stone is part of - unsigned int connectedSquare[size][4]; // static array containg the index of the neighbour or "size" - unsigned int neighbour[size][2][2]; // static array containing the two neighbours of each squares - unsigned int stonesSet; // number of stones set in the setting phase - bool settingPhase; // true if stonesSet < 18 - unsigned int stoneMustBeRemoved; // number of stones which must be removed by the current player - Player *curPlayer, *oppPlayer; // pointers to the current and opponent player + // variables + int board[size]; // one of the values above for each board position + unsigned int warnings[size]; // array containing the warnings for each board position + bool stoneMoveAble[size][4]; // true if stone can be moved in this direction + unsigned int stonePartOfMill[size]; // the number of mills, of which this stone is part of + unsigned int connectedSquare[size][4]; // static array containg the index of the neighbour or "size" + unsigned int neighbour[size][2][2]; // static array containing the two neighbours of each squares + unsigned int stonesSet; // number of stones set in the setting phase + bool settingPhase; // true if stonesSet < 18 + unsigned int stoneMustBeRemoved; // number of stones which must be removed by the current player + Player *curPlayer, *oppPlayer; // pointers to the current and opponent player - // useful functions - void printBoard(); - void copyBoard(fieldStruct *destination); - void createBoard(); - void deleteBoard(); + // useful functions + void printBoard(); + void copyBoard(fieldStruct *destination); + void createBoard(); + void deleteBoard(); private: - // helper functions - char GetCharFromStone(int stone); - void setConnection(unsigned int index, int firstDirection, int secondDirection, int thirdDirection, int fourthDirection); - void setNeighbour(unsigned int index, unsigned int firstNeighbour0, unsigned int secondNeighbour0, unsigned int firstNeighbour1, unsigned int secondNeighbour1); + // helper functions + char GetCharFromStone(int stone); + void setConnection(unsigned int index, int firstDirection, int secondDirection, int thirdDirection, int fourthDirection); + void setNeighbour(unsigned int index, unsigned int firstNeighbour0, unsigned int secondNeighbour0, unsigned int firstNeighbour1, unsigned int secondNeighbour1); }; class MillAI abstract { protected: - fieldStruct dummyField; + fieldStruct dummyField; public: - // Constructor / destructor - MillAI() - { - dummyField.createBoard(); - }; - ~MillAI() - { - dummyField.deleteBoard(); - }; + // Constructor / destructor + MillAI() + { + dummyField.createBoard(); + }; + ~MillAI() + { + dummyField.deleteBoard(); + }; - // Functions - virtual void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo) = 0; + // Functions + virtual void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo) = 0; }; #endif diff --git a/src/perfect/minMaxKI.cpp b/src/perfect/minMaxKI.cpp index 9daa1536..9baf06ae 100644 --- a/src/perfect/minMaxKI.cpp +++ b/src/perfect/minMaxKI.cpp @@ -1,9 +1,9 @@ /********************************************************************* - MiniMaxAI.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + MiniMaxAI.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMaxAI.h" @@ -14,7 +14,7 @@ //----------------------------------------------------------------------------- MiniMaxAI::MiniMaxAI() { - depthOfFullTree = 0; + depthOfFullTree = 0; } //----------------------------------------------------------------------------- @@ -31,65 +31,57 @@ MiniMaxAI::~MiniMaxAI() //----------------------------------------------------------------------------- void MiniMaxAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo) { - // globals - field = theField; - ownId = field->curPlayer->id; - curSearchDepth = 0; - unsigned int bestChoice; - unsigned int searchDepth; + // globals + field = theField; + ownId = field->curPlayer->id; + curSearchDepth = 0; + unsigned int bestChoice; + unsigned int searchDepth; - // automatic depth - if (depthOfFullTree == 0) - { - if (theField->settingPhase) - searchDepth = 5; - else if (theField->curPlayer->numStones <= 4) - searchDepth = 7; - else if (theField->oppPlayer->numStones <= 4) - searchDepth = 7; - else - searchDepth = 7; - } - else - { - searchDepth = depthOfFullTree; - } + // automatic depth + if (depthOfFullTree == 0) { + if (theField->settingPhase) + searchDepth = 5; + else if (theField->curPlayer->numStones <= 4) + searchDepth = 7; + else if (theField->oppPlayer->numStones <= 4) + searchDepth = 7; + else + searchDepth = 7; + } else { + searchDepth = depthOfFullTree; + } - // Inform user about progress - cout << "MiniMaxAI is thinking with a depth of " << searchDepth << " steps!\n\n\n"; + // Inform user about progress + cout << "MiniMaxAI is thinking with a depth of " << searchDepth << " steps!\n\n\n"; - // reserve memory - possibilities = new Possibility[searchDepth + 1]; - oldStates = new Backup[searchDepth + 1]; - idPossibilities = new unsigned int[(searchDepth + 1) * MAX_NUM_POS_MOVES]; + // reserve memory + possibilities = new Possibility[searchDepth + 1]; + oldStates = new Backup[searchDepth + 1]; + idPossibilities = new unsigned int[(searchDepth + 1) * MAX_NUM_POS_MOVES]; - // start the miniMax-algorithmn - Possibility *rootPossibilities = (Possibility *)getBestChoice(searchDepth, &bestChoice, MAX_NUM_POS_MOVES); + // start the miniMax-algorithmn + Possibility *rootPossibilities = (Possibility *)getBestChoice(searchDepth, &bestChoice, MAX_NUM_POS_MOVES); - // decode the best choice - if (field->stoneMustBeRemoved) - { - *pushFrom = bestChoice; - *pushTo = 0; - } - else if (field->settingPhase) - { - *pushFrom = 0; - *pushTo = bestChoice; - } - else - { - *pushFrom = rootPossibilities->from[bestChoice]; - *pushTo = rootPossibilities->to[bestChoice]; - } + // decode the best choice + if (field->stoneMustBeRemoved) { + *pushFrom = bestChoice; + *pushTo = 0; + } else if (field->settingPhase) { + *pushFrom = 0; + *pushTo = bestChoice; + } else { + *pushFrom = rootPossibilities->from[bestChoice]; + *pushTo = rootPossibilities->to[bestChoice]; + } - // release memory - delete[] oldStates; - delete[] idPossibilities; - delete[] possibilities; + // release memory + delete[] oldStates; + delete[] idPossibilities; + delete[] possibilities; - // release memory - field = nullptr; + // release memory + field = nullptr; } //----------------------------------------------------------------------------- @@ -98,7 +90,7 @@ void MiniMaxAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int //----------------------------------------------------------------------------- void MiniMaxAI::setSearchDepth(unsigned int depth) { - depthOfFullTree = depth; + depthOfFullTree = depth; } //----------------------------------------------------------------------------- @@ -107,9 +99,9 @@ void MiniMaxAI::setSearchDepth(unsigned int depth) //----------------------------------------------------------------------------- void MiniMaxAI::prepareBestChoiceCalculation() { - // calculate current value - currentValue = 0; - gameHasFinished = false; + // calculate current value + currentValue = 0; + gameHasFinished = false; } //----------------------------------------------------------------------------- @@ -118,27 +110,25 @@ void MiniMaxAI::prepareBestChoiceCalculation() //----------------------------------------------------------------------------- unsigned int *MiniMaxAI::getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int i; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + // locals + unsigned int i; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - // possibilities with cut off - for ((*numPossibilities) = 0, i = 0; i < field->size; i++) - { + // possibilities with cut off + for ((*numPossibilities) = 0, i = 0; i < field->size; i++) { - // move possible ? - if (field->board[i] == field->squareIsFree) - { + // move possible ? + if (field->board[i] == field->squareIsFree) { - idPossibility[*numPossibilities] = i; - (*numPossibilities)++; - } - } + idPossibility[*numPossibilities] = i; + (*numPossibilities)++; + } + } - // possibility code is simple - *pPossibilities = nullptr; + // possibility code is simple + *pPossibilities = nullptr; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -147,64 +137,55 @@ unsigned int *MiniMaxAI::getPossSettingPhase(unsigned int *numPossibilities, voi //----------------------------------------------------------------------------- unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int from, to, dir; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - Possibility *possibility = &possibilities[curSearchDepth]; + // locals + unsigned int from, to, dir; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + Possibility *possibility = &possibilities[curSearchDepth]; - // if he is not allowed to spring - if (field->curPlayer->numStones > 3) - { + // if he is not allowed to spring + if (field->curPlayer->numStones > 3) { - for ((*numPossibilities) = 0, from = 0; from < field->size; from++) - { - for (dir = 0; dir < 4; dir++) - { + for ((*numPossibilities) = 0, from = 0; from < field->size; from++) { + for (dir = 0; dir < 4; dir++) { - // destination - to = field->connectedSquare[from][dir]; + // destination + to = field->connectedSquare[from][dir]; - // move possible ? - if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) - { + // move possible ? + if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) { - // stone is moveable - idPossibility[*numPossibilities] = *numPossibilities; - possibility->from[*numPossibilities] = from; - possibility->to[*numPossibilities] = to; - (*numPossibilities)++; + // stone is moveable + idPossibility[*numPossibilities] = *numPossibilities; + possibility->from[*numPossibilities] = from; + possibility->to[*numPossibilities] = to; + (*numPossibilities)++; - // current player is allowed to spring - } - } - } - } - else - { + // current player is allowed to spring + } + } + } + } else { - for ((*numPossibilities) = 0, from = 0; from < field->size; from++) - { - for (to = 0; to < field->size; to++) - { + for ((*numPossibilities) = 0, from = 0; from < field->size; from++) { + for (to = 0; to < field->size; to++) { - // move possible ? - if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) - { + // move possible ? + if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) { - // stone is moveable - idPossibility[*numPossibilities] = *numPossibilities; - possibility->from[*numPossibilities] = from; - possibility->to[*numPossibilities] = to; - (*numPossibilities)++; - } - } - } - } + // stone is moveable + idPossibility[*numPossibilities] = *numPossibilities; + possibility->from[*numPossibilities] = from; + possibility->to[*numPossibilities] = to; + (*numPossibilities)++; + } + } + } + } - // pass possibilities - *pPossibilities = (void *)possibility; + // pass possibilities + *pPossibilities = (void *)possibility; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -213,27 +194,25 @@ unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void //----------------------------------------------------------------------------- unsigned int *MiniMaxAI::getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int i; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + // locals + unsigned int i; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - // possibilities with cut off - for ((*numPossibilities) = 0, i = 0; i < field->size; i++) - { + // possibilities with cut off + for ((*numPossibilities) = 0, i = 0; i < field->size; i++) { - // move possible ? - if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) - { + // move possible ? + if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) { - idPossibility[*numPossibilities] = i; - (*numPossibilities)++; - } - } + idPossibility[*numPossibilities] = i; + (*numPossibilities)++; + } + } - // possibility code is simple - *pPossibilities = nullptr; + // possibility code is simple + *pPossibilities = nullptr; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -242,25 +221,22 @@ unsigned int *MiniMaxAI::getPossStoneRemove(unsigned int *numPossibilities, void //----------------------------------------------------------------------------- unsigned int *MiniMaxAI::getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities) { - // set opponentsMove - *opponentsMove = (field->curPlayer->id == ownId) ? false : true; + // set opponentsMove + *opponentsMove = (field->curPlayer->id == ownId) ? false : true; - // When game has ended of course nothing happens any more - if (gameHasFinished) - { - *numPossibilities = 0; - return 0; - // look what is to do - } - else - { - if (field->stoneMustBeRemoved) - return getPossStoneRemove(numPossibilities, pPossibilities); - else if (field->settingPhase) - return getPossSettingPhase(numPossibilities, pPossibilities); - else - return getPossNormalMove(numPossibilities, pPossibilities); - } + // When game has ended of course nothing happens any more + if (gameHasFinished) { + *numPossibilities = 0; + return 0; + // look what is to do + } else { + if (field->stoneMustBeRemoved) + return getPossStoneRemove(numPossibilities, pPossibilities); + else if (field->settingPhase) + return getPossSettingPhase(numPossibilities, pPossibilities); + else + return getPossNormalMove(numPossibilities, pPossibilities); + } } //----------------------------------------------------------------------------- @@ -269,8 +245,8 @@ unsigned int *MiniMaxAI::getPossibilities(unsigned int threadNo, unsigned int *n //----------------------------------------------------------------------------- void MiniMaxAI::getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue) { - floatValue = currentValue; - shortValue = 0; + floatValue = currentValue; + shortValue = 0; } //----------------------------------------------------------------------------- @@ -287,34 +263,33 @@ void MiniMaxAI::deletePossibilities(unsigned int threadNo, void *pPossibilities) //----------------------------------------------------------------------------- void MiniMaxAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities) { - // locals - Backup *oldState = (Backup *)pBackup; + // locals + Backup *oldState = (Backup *)pBackup; - // reset old value - currentValue = oldState->value; - gameHasFinished = oldState->gameHasFinished; - curSearchDepth--; + // reset old value + currentValue = oldState->value; + gameHasFinished = oldState->gameHasFinished; + curSearchDepth--; - field->curPlayer = oldState->curPlayer; - field->oppPlayer = oldState->oppPlayer; - field->curPlayer->numStones = oldState->curNumStones; - field->oppPlayer->numStones = oldState->oppNumStones; - field->curPlayer->numStonesMissing = oldState->curMissStones; - field->oppPlayer->numStonesMissing = oldState->oppMissStones; - field->curPlayer->numPossibleMoves = oldState->curPosMoves; - field->oppPlayer->numPossibleMoves = oldState->oppPosMoves; - field->settingPhase = oldState->settingPhase; - field->stonesSet = oldState->stonesSet; - field->stoneMustBeRemoved = oldState->stoneMustBeRemoved; - field->board[oldState->from] = oldState->fieldFrom; - field->board[oldState->to] = oldState->fieldTo; + field->curPlayer = oldState->curPlayer; + field->oppPlayer = oldState->oppPlayer; + field->curPlayer->numStones = oldState->curNumStones; + field->oppPlayer->numStones = oldState->oppNumStones; + field->curPlayer->numStonesMissing = oldState->curMissStones; + field->oppPlayer->numStonesMissing = oldState->oppMissStones; + field->curPlayer->numPossibleMoves = oldState->curPosMoves; + field->oppPlayer->numPossibleMoves = oldState->oppPosMoves; + field->settingPhase = oldState->settingPhase; + field->stonesSet = oldState->stonesSet; + field->stoneMustBeRemoved = oldState->stoneMustBeRemoved; + field->board[oldState->from] = oldState->fieldFrom; + field->board[oldState->to] = oldState->fieldTo; - // very expensive - for (int i = 0; i < field->size; i++) - { - field->stonePartOfMill[i] = oldState->stonePartOfMill[i]; - field->warnings[i] = oldState->warnings[i]; - } + // very expensive + for (int i = 0; i < field->size; i++) { + field->stonePartOfMill[i] = oldState->stonePartOfMill[i]; + field->warnings[i] = oldState->warnings[i]; + } } //----------------------------------------------------------------------------- @@ -323,81 +298,73 @@ void MiniMaxAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opp //----------------------------------------------------------------------------- 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 (field->board[stoneOne] == field->curPlayer->id && field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) - { + // 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) { - field->stonePartOfMill[stoneOne]++; - field->stonePartOfMill[stoneTwo]++; - field->stonePartOfMill[stoneThree]++; - field->stoneMustBeRemoved = 1; - } + field->stonePartOfMill[stoneOne]++; + field->stonePartOfMill[stoneTwo]++; + field->stonePartOfMill[stoneThree]++; + field->stoneMustBeRemoved = 1; + } - // is a mill destroyed ? - if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) - { + // is a mill destroyed ? + if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) { - field->stonePartOfMill[stoneOne]--; - field->stonePartOfMill[stoneTwo]--; - field->stonePartOfMill[stoneThree]--; - } + field->stonePartOfMill[stoneOne]--; + field->stonePartOfMill[stoneTwo]--; + field->stonePartOfMill[stoneThree]--; + } - // stone was set - if (field->board[stoneOne] == field->curPlayer->id) - { + // stone was set + if (field->board[stoneOne] == field->curPlayer->id) { - // a warnig was destroyed - field->warnings[stoneOne] = field->noWarning; + // a warnig was destroyed + field->warnings[stoneOne] = field->noWarning; - // a warning is created - if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->squareIsFree) - field->warnings[stoneThree] |= field->curPlayer->warning; - if (field->board[stoneThree] == field->curPlayer->id && field->board[stoneTwo] == field->squareIsFree) - field->warnings[stoneTwo] |= field->curPlayer->warning; + // a warning is created + if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->squareIsFree) + field->warnings[stoneThree] |= field->curPlayer->warning; + if (field->board[stoneThree] == field->curPlayer->id && field->board[stoneTwo] == field->squareIsFree) + field->warnings[stoneTwo] |= field->curPlayer->warning; - // stone was removed - } - else if (field->board[stoneOne] == field->squareIsFree) - { + // stone was removed + } else if (field->board[stoneOne] == field->squareIsFree) { - // a warning is created - if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) - field->warnings[stoneOne] |= field->curPlayer->warning; - if (field->board[stoneTwo] == field->oppPlayer->id && field->board[stoneThree] == field->oppPlayer->id) - field->warnings[stoneOne] |= field->oppPlayer->warning; + // a warning is created + if (field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) + field->warnings[stoneOne] |= field->curPlayer->warning; + if (field->board[stoneTwo] == field->oppPlayer->id && field->board[stoneThree] == field->oppPlayer->id) + field->warnings[stoneOne] |= field->oppPlayer->warning; - // a warning is destroyed - if (field->warnings[stoneTwo] && field->board[stoneThree] != field->squareIsFree) - { + // a warning is destroyed + if (field->warnings[stoneTwo] && field->board[stoneThree] != field->squareIsFree) { - // 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) - field->warnings[stoneTwo] = field->curPlayer->warning; - else if (field->board[field->neighbour[stoneTwo][1][0]] == field->curPlayer->id && field->board[field->neighbour[stoneTwo][1][1]] == field->curPlayer->id) - field->warnings[stoneTwo] = field->curPlayer->warning; - else if (field->board[field->neighbour[stoneTwo][0][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneTwo][0][1]] == field->oppPlayer->id) - field->warnings[stoneTwo] = field->oppPlayer->warning; - else if (field->board[field->neighbour[stoneTwo][1][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneTwo][1][1]] == field->oppPlayer->id) - field->warnings[stoneTwo] = field->oppPlayer->warning; - else - field->warnings[stoneTwo] = field->noWarning; - } - else if (field->warnings[stoneThree] && field->board[stoneTwo] != field->squareIsFree) - { + // 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) + field->warnings[stoneTwo] = field->curPlayer->warning; + else if (field->board[field->neighbour[stoneTwo][1][0]] == field->curPlayer->id && field->board[field->neighbour[stoneTwo][1][1]] == field->curPlayer->id) + field->warnings[stoneTwo] = field->curPlayer->warning; + else if (field->board[field->neighbour[stoneTwo][0][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneTwo][0][1]] == field->oppPlayer->id) + field->warnings[stoneTwo] = field->oppPlayer->warning; + else if (field->board[field->neighbour[stoneTwo][1][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneTwo][1][1]] == field->oppPlayer->id) + field->warnings[stoneTwo] = field->oppPlayer->warning; + else + field->warnings[stoneTwo] = field->noWarning; + } else if (field->warnings[stoneThree] && field->board[stoneTwo] != field->squareIsFree) { - // 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) - field->warnings[stoneThree] = field->curPlayer->warning; - else if (field->board[field->neighbour[stoneThree][1][0]] == field->curPlayer->id && field->board[field->neighbour[stoneThree][1][1]] == field->curPlayer->id) - field->warnings[stoneThree] = field->curPlayer->warning; - else if (field->board[field->neighbour[stoneThree][0][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneThree][0][1]] == field->oppPlayer->id) - field->warnings[stoneThree] = field->oppPlayer->warning; - else if (field->board[field->neighbour[stoneThree][1][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneThree][1][1]] == field->oppPlayer->id) - field->warnings[stoneThree] = field->oppPlayer->warning; - else - field->warnings[stoneThree] = field->noWarning; - } - } + // 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) + field->warnings[stoneThree] = field->curPlayer->warning; + else if (field->board[field->neighbour[stoneThree][1][0]] == field->curPlayer->id && field->board[field->neighbour[stoneThree][1][1]] == field->curPlayer->id) + field->warnings[stoneThree] = field->curPlayer->warning; + else if (field->board[field->neighbour[stoneThree][0][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneThree][0][1]] == field->oppPlayer->id) + field->warnings[stoneThree] = field->oppPlayer->warning; + else if (field->board[field->neighbour[stoneThree][1][0]] == field->oppPlayer->id && field->board[field->neighbour[stoneThree][1][1]] == field->oppPlayer->id) + field->warnings[stoneThree] = field->oppPlayer->warning; + else + field->warnings[stoneThree] = field->noWarning; + } + } } //----------------------------------------------------------------------------- @@ -406,29 +373,28 @@ inline void MiniMaxAI::setWarning(unsigned int stoneOne, unsigned int stoneTwo, //----------------------------------------------------------------------------- inline void MiniMaxAI::updateWarning(unsigned int firstStone, unsigned int secondStone) { - // set warnings - if (firstStone < field->size) - setWarning(firstStone, field->neighbour[firstStone][0][0], field->neighbour[firstStone][0][1]); - if (firstStone < field->size) - setWarning(firstStone, field->neighbour[firstStone][1][0], field->neighbour[firstStone][1][1]); + // set warnings + if (firstStone < field->size) + setWarning(firstStone, field->neighbour[firstStone][0][0], field->neighbour[firstStone][0][1]); + if (firstStone < field->size) + setWarning(firstStone, field->neighbour[firstStone][1][0], field->neighbour[firstStone][1][1]); - if (secondStone < field->size) - setWarning(secondStone, field->neighbour[secondStone][0][0], field->neighbour[secondStone][0][1]); - if (secondStone < field->size) - setWarning(secondStone, field->neighbour[secondStone][1][0], field->neighbour[secondStone][1][1]); + if (secondStone < field->size) + setWarning(secondStone, field->neighbour[secondStone][0][0], field->neighbour[secondStone][0][1]); + if (secondStone < field->size) + setWarning(secondStone, field->neighbour[secondStone][1][0], field->neighbour[secondStone][1][1]); - // no stone must be removed if each belongs to a mill - unsigned int i; - bool atLeastOneStoneRemoveAble = false; - if (field->stoneMustBeRemoved) - for (i = 0; i < field->size; i++) - if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) - { - atLeastOneStoneRemoveAble = true; - break; - } - if (!atLeastOneStoneRemoveAble) - field->stoneMustBeRemoved = 0; + // no stone must be removed if each belongs to a mill + unsigned int i; + bool atLeastOneStoneRemoveAble = false; + if (field->stoneMustBeRemoved) + for (i = 0; i < field->size; i++) + if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) { + atLeastOneStoneRemoveAble = true; + break; + } + if (!atLeastOneStoneRemoveAble) + field->stoneMustBeRemoved = 0; } //----------------------------------------------------------------------------- @@ -437,58 +403,51 @@ inline void MiniMaxAI::updateWarning(unsigned int firstStone, unsigned int secon //----------------------------------------------------------------------------- inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone) { - // locals - unsigned int neighbor, direction; + // locals + unsigned int neighbor, direction; - // look into every direction - for (direction = 0; direction < 4; direction++) - { + // look into every direction + for (direction = 0; direction < 4; direction++) { - neighbor = field->connectedSquare[stone][direction]; + neighbor = field->connectedSquare[stone][direction]; - // neighbor must exist - if (neighbor < field->size) - { + // neighbor must exist + if (neighbor < field->size) { - // relevant when moving from one square to another connected square - if (ignoreStone == neighbor) - continue; + // relevant when moving from one square to another connected square + if (ignoreStone == neighbor) + continue; - // if there is no neighbour stone than it only affects the actual stone - if (field->board[neighbor] == field->squareIsFree) - { + // if there is no neighbour stone than it only affects the actual stone + if (field->board[neighbor] == field->squareIsFree) { - if (stoneRemoved) - stoneOwner->numPossibleMoves--; - else - stoneOwner->numPossibleMoves++; + if (stoneRemoved) + stoneOwner->numPossibleMoves--; + else + stoneOwner->numPossibleMoves++; - // if there is a neighbour stone than it effects only this one - } - else if (field->board[neighbor] == field->curPlayer->id) - { + // if there is a neighbour stone than it effects only this one + } else if (field->board[neighbor] == field->curPlayer->id) { - if (stoneRemoved) - field->curPlayer->numPossibleMoves++; - else - field->curPlayer->numPossibleMoves--; - } - else - { + if (stoneRemoved) + field->curPlayer->numPossibleMoves++; + else + field->curPlayer->numPossibleMoves--; + } else { - if (stoneRemoved) - field->oppPlayer->numPossibleMoves++; - else - field->oppPlayer->numPossibleMoves--; - } - } - } + if (stoneRemoved) + field->oppPlayer->numPossibleMoves++; + else + field->oppPlayer->numPossibleMoves--; + } + } + } - // only 3 stones resting - if (field->curPlayer->numStones <= 3 && !field->settingPhase) - field->curPlayer->numPossibleMoves = field->curPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); - if (field->oppPlayer->numStones <= 3 && !field->settingPhase) - field->oppPlayer->numPossibleMoves = field->oppPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); + // only 3 stones resting + if (field->curPlayer->numStones <= 3 && !field->settingPhase) + field->curPlayer->numPossibleMoves = field->curPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); + if (field->oppPlayer->numStones <= 3 && !field->settingPhase) + field->oppPlayer->numPossibleMoves = field->oppPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); } //----------------------------------------------------------------------------- @@ -497,26 +456,26 @@ inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwne //----------------------------------------------------------------------------- inline void MiniMaxAI::setStone(unsigned int to, Backup *backup) { - // backup - backup->from = field->size; - backup->to = to; - backup->fieldFrom = field->size; - backup->fieldTo = field->board[to]; + // backup + backup->from = field->size; + backup->to = to; + backup->fieldFrom = field->size; + backup->fieldTo = field->board[to]; - // set stone into board - field->board[to] = field->curPlayer->id; - field->curPlayer->numStones++; - field->stonesSet++; + // set stone into board + field->board[to] = field->curPlayer->id; + field->curPlayer->numStones++; + field->stonesSet++; - // setting phase finished ? - if (field->stonesSet == 18) - field->settingPhase = false; + // setting phase finished ? + if (field->stonesSet == 18) + field->settingPhase = false; - // update possible moves - updatePossibleMoves(to, field->curPlayer, false, field->size); + // update possible moves + updatePossibleMoves(to, field->curPlayer, false, field->size); - // update warnings - updateWarning(to, field->size); + // update warnings + updateWarning(to, field->size); } //----------------------------------------------------------------------------- @@ -525,22 +484,22 @@ inline void MiniMaxAI::setStone(unsigned int to, Backup *backup) //----------------------------------------------------------------------------- inline void MiniMaxAI::normalMove(unsigned int from, unsigned int to, Backup *backup) { - // backup - backup->from = from; - backup->to = to; - backup->fieldFrom = field->board[from]; - backup->fieldTo = field->board[to]; + // backup + backup->from = from; + backup->to = to; + backup->fieldFrom = field->board[from]; + backup->fieldTo = field->board[to]; - // set stone into board - field->board[from] = field->squareIsFree; - field->board[to] = field->curPlayer->id; + // set stone into board + field->board[from] = field->squareIsFree; + field->board[to] = field->curPlayer->id; - // update possible moves - updatePossibleMoves(from, field->curPlayer, true, to); - updatePossibleMoves(to, field->curPlayer, false, from); + // update possible moves + updatePossibleMoves(from, field->curPlayer, true, to); + updatePossibleMoves(to, field->curPlayer, false, from); - // update warnings - updateWarning(from, to); + // update warnings + updateWarning(from, to); } //----------------------------------------------------------------------------- @@ -549,27 +508,27 @@ inline void MiniMaxAI::normalMove(unsigned int from, unsigned int to, Backup *ba //----------------------------------------------------------------------------- inline void MiniMaxAI::removeStone(unsigned int from, Backup *backup) { - // backup - backup->from = from; - backup->to = field->size; - backup->fieldFrom = field->board[from]; - backup->fieldTo = field->size; + // backup + backup->from = from; + backup->to = field->size; + backup->fieldFrom = field->board[from]; + backup->fieldTo = field->size; - // remove stone - field->board[from] = field->squareIsFree; - field->oppPlayer->numStones--; - field->oppPlayer->numStonesMissing++; - field->stoneMustBeRemoved--; + // remove stone + field->board[from] = field->squareIsFree; + field->oppPlayer->numStones--; + field->oppPlayer->numStonesMissing++; + field->stoneMustBeRemoved--; - // update possible moves - updatePossibleMoves(from, field->oppPlayer, true, field->size); + // update possible moves + updatePossibleMoves(from, field->oppPlayer, true, field->size); - // update warnings - updateWarning(from, field->size); + // update warnings + updateWarning(from, field->size); - // end of game ? - if ((field->oppPlayer->numStones < 3) && (!field->settingPhase)) - gameHasFinished = true; + // end of game ? + if ((field->oppPlayer->numStones < 3) && (!field->settingPhase)) + gameHasFinished = true; } //----------------------------------------------------------------------------- @@ -578,73 +537,66 @@ inline void MiniMaxAI::removeStone(unsigned int from, Backup *backup) //----------------------------------------------------------------------------- void MiniMaxAI::move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities) { - // locals - Backup *oldState = &oldStates[curSearchDepth]; - Possibility *tmpPossibility = (Possibility *)pPossibilities; - Player *tmpPlayer; - unsigned int i; + // locals + Backup *oldState = &oldStates[curSearchDepth]; + Possibility *tmpPossibility = (Possibility *)pPossibilities; + Player *tmpPlayer; + unsigned int i; - // calculate place of stone - *pBackup = (void *)oldState; - oldState->value = currentValue; - oldState->gameHasFinished = gameHasFinished; - oldState->curPlayer = field->curPlayer; - oldState->oppPlayer = field->oppPlayer; - oldState->curNumStones = field->curPlayer->numStones; - oldState->oppNumStones = field->oppPlayer->numStones; - oldState->curPosMoves = field->curPlayer->numPossibleMoves; - oldState->oppPosMoves = field->oppPlayer->numPossibleMoves; - oldState->curMissStones = field->curPlayer->numStonesMissing; - oldState->oppMissStones = field->oppPlayer->numStonesMissing; - oldState->settingPhase = field->settingPhase; - oldState->stonesSet = field->stonesSet; - oldState->stoneMustBeRemoved = field->stoneMustBeRemoved; - curSearchDepth++; + // calculate place of stone + *pBackup = (void *)oldState; + oldState->value = currentValue; + oldState->gameHasFinished = gameHasFinished; + oldState->curPlayer = field->curPlayer; + oldState->oppPlayer = field->oppPlayer; + oldState->curNumStones = field->curPlayer->numStones; + oldState->oppNumStones = field->oppPlayer->numStones; + oldState->curPosMoves = field->curPlayer->numPossibleMoves; + oldState->oppPosMoves = field->oppPlayer->numPossibleMoves; + oldState->curMissStones = field->curPlayer->numStonesMissing; + oldState->oppMissStones = field->oppPlayer->numStonesMissing; + oldState->settingPhase = field->settingPhase; + oldState->stonesSet = field->stonesSet; + oldState->stoneMustBeRemoved = field->stoneMustBeRemoved; + curSearchDepth++; - // very expensive - for (i = 0; i < field->size; i++) - { - oldState->stonePartOfMill[i] = field->stonePartOfMill[i]; - oldState->warnings[i] = field->warnings[i]; - } + // very expensive + for (i = 0; i < field->size; i++) { + oldState->stonePartOfMill[i] = field->stonePartOfMill[i]; + oldState->warnings[i] = field->warnings[i]; + } - // move - if (field->stoneMustBeRemoved) - { - removeStone(idPossibility, oldState); - } - else if (field->settingPhase) - { - setStone(idPossibility, oldState); - } - else - { - normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState); - } + // move + if (field->stoneMustBeRemoved) { + removeStone(idPossibility, oldState); + } else if (field->settingPhase) { + setStone(idPossibility, oldState); + } else { + normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState); + } - // when opponent is unable to move than current player has won - if ((!field->oppPlayer->numPossibleMoves) && (!field->settingPhase) && (!field->stoneMustBeRemoved) && (field->oppPlayer->numStones > 3)) - gameHasFinished = true; + // when opponent is unable to move than current player has won + if ((!field->oppPlayer->numPossibleMoves) && (!field->settingPhase) && (!field->stoneMustBeRemoved) && (field->oppPlayer->numStones > 3)) + gameHasFinished = true; - // calc value - if (!opponentsMove) - currentValue = (float)field->oppPlayer->numStonesMissing - field->curPlayer->numStonesMissing + field->stoneMustBeRemoved + field->curPlayer->numPossibleMoves * 0.1f - field->oppPlayer->numPossibleMoves * 0.1f; - else - currentValue = (float)field->curPlayer->numStonesMissing - field->oppPlayer->numStonesMissing - field->stoneMustBeRemoved + field->oppPlayer->numPossibleMoves * 0.1f - field->curPlayer->numPossibleMoves * 0.1f; + // calc value + if (!opponentsMove) + currentValue = (float)field->oppPlayer->numStonesMissing - field->curPlayer->numStonesMissing + field->stoneMustBeRemoved + field->curPlayer->numPossibleMoves * 0.1f - field->oppPlayer->numPossibleMoves * 0.1f; + else + currentValue = (float)field->curPlayer->numStonesMissing - field->oppPlayer->numStonesMissing - field->stoneMustBeRemoved + field->oppPlayer->numPossibleMoves * 0.1f - field->curPlayer->numPossibleMoves * 0.1f; - // when game has finished - perfect for the current player - if (gameHasFinished && !opponentsMove) - currentValue = VALUE_GAME_WON - curSearchDepth; - if (gameHasFinished && opponentsMove) - currentValue = VALUE_GAME_LOST + curSearchDepth; + // when game has finished - perfect for the current player + if (gameHasFinished && !opponentsMove) + currentValue = VALUE_GAME_WON - curSearchDepth; + if (gameHasFinished && opponentsMove) + currentValue = VALUE_GAME_LOST + curSearchDepth; - // set next player - if (!field->stoneMustBeRemoved) - { - tmpPlayer = field->curPlayer; - field->curPlayer = field->oppPlayer; - field->oppPlayer = tmpPlayer; - } + // set next player + if (!field->stoneMustBeRemoved) { + tmpPlayer = field->curPlayer; + field->curPlayer = field->oppPlayer; + field->oppPlayer = tmpPlayer; + } } //----------------------------------------------------------------------------- @@ -653,14 +605,14 @@ void MiniMaxAI::move(unsigned int threadNo, unsigned int idPossibility, bool opp //----------------------------------------------------------------------------- void MiniMaxAI::printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities) { - // locals - Possibility *tmpPossibility = (Possibility *)pPossibilities; + // locals + Possibility *tmpPossibility = (Possibility *)pPossibilities; - // move - if (field->stoneMustBeRemoved) - cout << "remove stone from " << (char)(idPossibility + 97); - else if (field->settingPhase) - cout << "set stone to " << (char)(idPossibility + 97); - else - cout << "move from " << (char)(tmpPossibility->from[idPossibility] + 97) << " to " << (char)(tmpPossibility->to[idPossibility] + 97); + // move + if (field->stoneMustBeRemoved) + cout << "remove stone from " << (char)(idPossibility + 97); + else if (field->settingPhase) + cout << "set stone to " << (char)(idPossibility + 97); + else + cout << "move from " << (char)(tmpPossibility->from[idPossibility] + 97) << " to " << (char)(tmpPossibility->to[idPossibility] + 97); } diff --git a/src/perfect/miniMax.cpp b/src/perfect/miniMax.cpp index 42398a40..b430aa0e 100644 --- a/src/perfect/miniMax.cpp +++ b/src/perfect/miniMax.cpp @@ -1,9 +1,9 @@ /********************************************************************* - MiniMax.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + MiniMax.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMax.h" @@ -14,64 +14,61 @@ //----------------------------------------------------------------------------- MiniMax::MiniMax() { - // init default values - hFileShortKnotValues = nullptr; - hFilePlyInfo = nullptr; - memoryUsed2 = 0; - arrayInfos.c = this; - arrayInfos.arrayInfosToBeUpdated.clear(); - arrayInfos.listArrays.clear(); - onlyPrepareLayer = false; - curCalculatedLayer = 0; - osPrint = &cout; - verbosity = 3; - stopOnCriticalError = true; - pDataForUserPrintFunc = nullptr; - userPrintFunc = nullptr; - layerStats = nullptr; - plyInfos = nullptr; - fileDirectory.assign(""); - InitializeCriticalSection(&csDatabase); - InitializeCriticalSection(&csOsPrint); + // init default values + hFileShortKnotValues = nullptr; + hFilePlyInfo = nullptr; + memoryUsed2 = 0; + arrayInfos.c = this; + arrayInfos.arrayInfosToBeUpdated.clear(); + arrayInfos.listArrays.clear(); + onlyPrepareLayer = false; + curCalculatedLayer = 0; + osPrint = &cout; + verbosity = 3; + stopOnCriticalError = true; + pDataForUserPrintFunc = nullptr; + userPrintFunc = nullptr; + layerStats = nullptr; + plyInfos = nullptr; + fileDirectory.assign(""); + InitializeCriticalSection(&csDatabase); + InitializeCriticalSection(&csOsPrint); - // Tausender-Trennzeichen - locale locale("German_Switzerland"); - cout.imbue(locale); + // Tausender-Trennzeichen + locale locale("German_Switzerland"); + cout.imbue(locale); - // for io operations per second measurement - QueryPerformanceFrequency(&frequency); - numReadSkvOperations = 0; - numWriteSkvOperations = 0; - numReadPlyOperations = 0; - numWritePlyOperations = 0; - if (MEASURE_ONLY_IO) - { - readSkvInterval.QuadPart = 0; - writeSkvInterval.QuadPart = 0; - readPlyInterval.QuadPart = 0; - writePlyInterval.QuadPart = 0; - } - else - { - QueryPerformanceCounter(&readSkvInterval); - QueryPerformanceCounter(&writeSkvInterval); - QueryPerformanceCounter(&readPlyInterval); - QueryPerformanceCounter(&writePlyInterval); - } + // for io operations per second measurement + QueryPerformanceFrequency(&frequency); + numReadSkvOperations = 0; + numWriteSkvOperations = 0; + numReadPlyOperations = 0; + numWritePlyOperations = 0; + if (MEASURE_ONLY_IO) { + readSkvInterval.QuadPart = 0; + writeSkvInterval.QuadPart = 0; + readPlyInterval.QuadPart = 0; + writePlyInterval.QuadPart = 0; + } else { + QueryPerformanceCounter(&readSkvInterval); + QueryPerformanceCounter(&writeSkvInterval); + QueryPerformanceCounter(&readPlyInterval); + QueryPerformanceCounter(&writePlyInterval); + } - // The algorithm assumes that each player does only one move. - // That means closing a mill and removing a stone should be one move. - // PL_TO_MOVE_CHANGED means that in the predecessor state the player to move has changed to the other player. - // PL_TO_MOVE_UNCHANGED means that the player to move is still the one who shall move. - unsigned char skvPerspectiveMatrixTmp[4][2] = { - // PL_TO_MOVE_UNCHANGED PL_TO_MOVE_CHANGED - SKV_VALUE_INVALID, SKV_VALUE_INVALID, // SKV_VALUE_INVALID - SKV_VALUE_GAME_WON, SKV_VALUE_GAME_LOST, // SKV_VALUE_GAME_LOST - SKV_VALUE_GAME_DRAWN, SKV_VALUE_GAME_DRAWN, // SKV_VALUE_GAME_DRAWN - SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON // SKV_VALUE_GAME_WON - }; + // The algorithm assumes that each player does only one move. + // That means closing a mill and removing a stone should be one move. + // PL_TO_MOVE_CHANGED means that in the predecessor state the player to move has changed to the other player. + // PL_TO_MOVE_UNCHANGED means that the player to move is still the one who shall move. + unsigned char skvPerspectiveMatrixTmp[4][2] = { + // PL_TO_MOVE_UNCHANGED PL_TO_MOVE_CHANGED + SKV_VALUE_INVALID, SKV_VALUE_INVALID, // SKV_VALUE_INVALID + SKV_VALUE_GAME_WON, SKV_VALUE_GAME_LOST, // SKV_VALUE_GAME_LOST + SKV_VALUE_GAME_DRAWN, SKV_VALUE_GAME_DRAWN, // SKV_VALUE_GAME_DRAWN + SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON // SKV_VALUE_GAME_WON + }; - memcpy(skvPerspectiveMatrix, skvPerspectiveMatrixTmp, 4 * 2); + memcpy(skvPerspectiveMatrix, skvPerspectiveMatrixTmp, 4 * 2); } //----------------------------------------------------------------------------- @@ -80,9 +77,9 @@ MiniMax::MiniMax() //----------------------------------------------------------------------------- MiniMax::~MiniMax() { - closeDatabase(); - DeleteCriticalSection(&csOsPrint); - DeleteCriticalSection(&csDatabase); + closeDatabase(); + DeleteCriticalSection(&csOsPrint); + DeleteCriticalSection(&csDatabase); } //----------------------------------------------------------------------------- @@ -91,9 +88,9 @@ MiniMax::~MiniMax() //----------------------------------------------------------------------------- bool MiniMax::falseOrStop() { - if (stopOnCriticalError) - WaitForSingleObject(GetCurrentProcess(), INFINITE); - return false; + if (stopOnCriticalError) + WaitForSingleObject(GetCurrentProcess(), INFINITE); + return false; } //----------------------------------------------------------------------------- @@ -102,30 +99,30 @@ bool MiniMax::falseOrStop() //----------------------------------------------------------------------------- void *MiniMax::getBestChoice(unsigned int tilLevel, unsigned int *choice, unsigned int maximumNumberOfBranches) { - // set global vars - depthOfFullTree = tilLevel; - maxNumBranches = maximumNumberOfBranches; - layerInDatabase = isCurrentStateInDatabase(0); - calcDatabase = false; + // set global vars + depthOfFullTree = tilLevel; + maxNumBranches = maximumNumberOfBranches; + layerInDatabase = isCurrentStateInDatabase(0); + calcDatabase = false; - // Locals - Node root; - AlphaBetaGlobalVars alphaBetaVars(this, getLayerNumber(0)); - RunAlphaBetaVars tva(this, &alphaBetaVars, alphaBetaVars.layerNumber); - srand((unsigned int)time(nullptr)); - tva.curThreadNo = 0; + // Locals + Node root; + AlphaBetaGlobalVars alphaBetaVars(this, getLayerNumber(0)); + RunAlphaBetaVars tva(this, &alphaBetaVars, alphaBetaVars.layerNumber); + srand((unsigned int)time(nullptr)); + tva.curThreadNo = 0; - // prepare the situation - prepareBestChoiceCalculation(); + // prepare the situation + prepareBestChoiceCalculation(); - // First make a tree until the desired level - letTheTreeGrow(&root, &tva, depthOfFullTree, FPKV_MIN_VALUE, FPKV_MAX_VALUE); + // First make a tree until the desired level + letTheTreeGrow(&root, &tva, depthOfFullTree, FPKV_MIN_VALUE, FPKV_MAX_VALUE); - // pass best choice and close database - *choice = root.bestMoveId; + // pass best choice and close database + *choice = root.bestMoveId; - // Return the best branch of the root - return pRootPossibilities; + // Return the best branch of the root + return pRootPossibilities; } //----------------------------------------------------------------------------- @@ -134,90 +131,85 @@ void *MiniMax::getBestChoice(unsigned int tilLevel, unsigned int *choice, unsign //----------------------------------------------------------------------------- void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLayer) { - // locals - bool abortCalculation = false; - this->onlyPrepareLayer = onlyPrepareLayer; - lastCalculatedLayer.clear(); + // locals + bool abortCalculation = false; + this->onlyPrepareLayer = onlyPrepareLayer; + lastCalculatedLayer.clear(); - PRINT(1, this, "*************************"); - PRINT(1, this, "* Calculate Database *"); - PRINT(1, this, "*************************"); + PRINT(1, this, "*************************"); + PRINT(1, this, "* Calculate Database *"); + PRINT(1, this, "*************************"); - // call preparation function of parent class - prepareDatabaseCalculation(); + // call preparation function of parent class + prepareDatabaseCalculation(); - // when database not completed then do it - if (hFileShortKnotValues != nullptr && skvfHeader.completed == false) - { + // when database not completed then do it + if (hFileShortKnotValues != nullptr && skvfHeader.completed == false) { - // reserve memory - lastCalculatedLayer.clear(); - depthOfFullTree = maxDepthOfTree; - layerInDatabase = false; - calcDatabase = true; - threadManager.uncancelExecution(); - arrayInfos.vectorArrays.resize(ArrayInfo::numArrayTypes * skvfHeader.numLayers, arrayInfos.listArrays.end()); + // reserve memory + lastCalculatedLayer.clear(); + depthOfFullTree = maxDepthOfTree; + layerInDatabase = false; + calcDatabase = true; + threadManager.uncancelExecution(); + arrayInfos.vectorArrays.resize(ArrayInfo::numArrayTypes * skvfHeader.numLayers, arrayInfos.listArrays.end()); - // calc layer after layer, beginning with the last one - for (curCalculatedLayer = 0; curCalculatedLayer < skvfHeader.numLayers; curCalculatedLayer++) - { + // calc layer after layer, beginning with the last one + for (curCalculatedLayer = 0; curCalculatedLayer < skvfHeader.numLayers; curCalculatedLayer++) { - // layer already calculated? - if (layerStats[curCalculatedLayer].layerIsCompletedAndInFile) - continue; + // layer already calculated? + if (layerStats[curCalculatedLayer].layerIsCompletedAndInFile) + continue; - // don't calc if neither the layer nor the partner layer has any knots - if (layerStats[curCalculatedLayer].knotsInLayer == 0 && layerStats[layerStats[curCalculatedLayer].partnerLayer].knotsInLayer == 0) - continue; + // don't calc if neither the layer nor the partner layer has any knots + if (layerStats[curCalculatedLayer].knotsInLayer == 0 && layerStats[layerStats[curCalculatedLayer].partnerLayer].knotsInLayer == 0) + continue; - // calc - abortCalculation = (!calcLayer(curCalculatedLayer)); + // calc + abortCalculation = (!calcLayer(curCalculatedLayer)); - // relase memory - unloadAllLayers(); - unloadAllPlyInfos(); + // relase memory + unloadAllLayers(); + unloadAllPlyInfos(); - // don't save layer and header when only preparing layers - if (onlyPrepareLayer) - return; - if (abortCalculation) - break; + // don't save layer and header when only preparing layers + if (onlyPrepareLayer) + return; + if (abortCalculation) + break; - // save header - saveHeader(&skvfHeader, layerStats); - saveHeader(&plyInfoHeader, plyInfos); - } + // save header + saveHeader(&skvfHeader, layerStats); + saveHeader(&plyInfoHeader, plyInfos); + } - // don't save layer and header when only preparing layers or when - if (onlyPrepareLayer) - return; - if (!abortCalculation) - { + // don't save layer and header when only preparing layers or when + if (onlyPrepareLayer) + return; + if (!abortCalculation) { - // calc layer statistics - calcLayerStatistics("statistics.txt"); + // calc layer statistics + calcLayerStatistics("statistics.txt"); - // save header - skvfHeader.completed = true; - plyInfoHeader.plyInfoCompleted = true; - saveHeader(&skvfHeader, layerStats); - saveHeader(&plyInfoHeader, plyInfos); - } + // save header + skvfHeader.completed = true; + plyInfoHeader.plyInfoCompleted = true; + saveHeader(&skvfHeader, layerStats); + saveHeader(&plyInfoHeader, plyInfos); + } - // free mem - curCalculationActionId = MM_ACTION_NONE; - } - else - { - PRINT(1, this, "\nThe database is already fully calculated.\n"); - } + // free mem + curCalculationActionId = MM_ACTION_NONE; + } else { + PRINT(1, this, "\nThe database is already fully calculated.\n"); + } - // call warp-up function of parent class - wrapUpDatabaseCalculation(abortCalculation); + // call warp-up function of parent class + wrapUpDatabaseCalculation(abortCalculation); - PRINT(1, this, "*************************"); - PRINT(1, this, "* Calculation finished *"); - PRINT(1, this, "*************************"); + PRINT(1, this, "*************************"); + PRINT(1, this, "* Calculation finished *"); + PRINT(1, this, "*************************"); } //----------------------------------------------------------------------------- @@ -226,64 +218,56 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay //----------------------------------------------------------------------------- bool MiniMax::calcLayer(unsigned int layerNumber) { - // locals - vector layersToCalculate; + // locals + vector layersToCalculate; - // moves can be done reverse, leading to too depth searching trees - if (shallRetroAnalysisBeUsed(layerNumber)) - { + // moves can be done reverse, leading to too depth searching trees + if (shallRetroAnalysisBeUsed(layerNumber)) { - // calc values for all states of layer - layersToCalculate.push_back(layerNumber); - if (layerNumber != layerStats[layerNumber].partnerLayer) - layersToCalculate.push_back(layerStats[layerNumber].partnerLayer); - if (!calcKnotValuesByRetroAnalysis(layersToCalculate)) - return false; + // calc values for all states of layer + layersToCalculate.push_back(layerNumber); + if (layerNumber != layerStats[layerNumber].partnerLayer) + layersToCalculate.push_back(layerStats[layerNumber].partnerLayer); + if (!calcKnotValuesByRetroAnalysis(layersToCalculate)) + return false; - // save partner layer - if (layerStats[layerNumber].partnerLayer != layerNumber) - { - saveLayerToFile(layerStats[layerNumber].partnerLayer); - } + // save partner layer + if (layerStats[layerNumber].partnerLayer != layerNumber) { + saveLayerToFile(layerStats[layerNumber].partnerLayer); + } - // use minimax-algorithm - } - else - { - if (!calcKnotValuesByAlphaBeta(layerNumber)) - return false; - } + // use minimax-algorithm + } else { + if (!calcKnotValuesByAlphaBeta(layerNumber)) + return false; + } - // save layer - saveLayerToFile(layerNumber); + // save layer + saveLayerToFile(layerNumber); - // test layer - if (!testLayer(layerNumber)) - { - PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); - return false; - } + // test layer + if (!testLayer(layerNumber)) { + PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); + return false; + } - // test partner layer if retro-analysis has been used - if (shallRetroAnalysisBeUsed(layerNumber) && layerStats[layerNumber].partnerLayer != layerNumber) - { - if (!testLayer(layerStats[layerNumber].partnerLayer)) - { - PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); - return false; - } - } + // test partner layer if retro-analysis has been used + if (shallRetroAnalysisBeUsed(layerNumber) && layerStats[layerNumber].partnerLayer != layerNumber) { + if (!testLayer(layerStats[layerNumber].partnerLayer)) { + PRINT(0, this, "ERROR: Layer calculation cancelled or failed!" << endl); + return false; + } + } - // update output information - EnterCriticalSection(&csOsPrint); - if (shallRetroAnalysisBeUsed(layerNumber) && layerNumber != layerStats[layerNumber].partnerLayer) - { - lastCalculatedLayer.push_back(layerStats[layerNumber].partnerLayer); - } - lastCalculatedLayer.push_back(layerNumber); - LeaveCriticalSection(&csOsPrint); + // update output information + EnterCriticalSection(&csOsPrint); + if (shallRetroAnalysisBeUsed(layerNumber) && layerNumber != layerStats[layerNumber].partnerLayer) { + lastCalculatedLayer.push_back(layerStats[layerNumber].partnerLayer); + } + lastCalculatedLayer.push_back(layerNumber); + LeaveCriticalSection(&csOsPrint); - return true; + return true; } //----------------------------------------------------------------------------- @@ -292,7 +276,7 @@ bool MiniMax::calcLayer(unsigned int layerNumber) //----------------------------------------------------------------------------- void MiniMax::pauseDatabaseCalculation() { - threadManager.pauseExecution(); + threadManager.pauseExecution(); } //----------------------------------------------------------------------------- @@ -301,8 +285,8 @@ void MiniMax::pauseDatabaseCalculation() //----------------------------------------------------------------------------- void MiniMax::cancelDatabaseCalculation() { - // when returning from executeParallelLoop() all function shall quit immediatelly up to calculateDatabase() - threadManager.cancelExecution(); + // when returning from executeParallelLoop() all function shall quit immediatelly up to calculateDatabase() + threadManager.cancelExecution(); } //----------------------------------------------------------------------------- @@ -311,5 +295,5 @@ void MiniMax::cancelDatabaseCalculation() //----------------------------------------------------------------------------- bool MiniMax::wasDatabaseCalculationCancelled() { - return threadManager.wasExecutionCancelled(); + return threadManager.wasExecutionCancelled(); } diff --git a/src/perfect/miniMax.h b/src/perfect/miniMax.h index 0296c394..195f59cc 100644 --- a/src/perfect/miniMax.h +++ b/src/perfect/miniMax.h @@ -1,9 +1,9 @@ /*************************************************************************************************************************** - miniMax.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp ***************************************************************************************************************************/ #ifndef MINIMAX_H @@ -121,635 +121,645 @@ database: The database contains the arrays with the short knot values and the /*** Klassen ***************************************************************************************************************************/ class MiniMax { - friend class MiniMaxWinInspectDb; - friend class MiniMaxWinCalcDb; + friend class MiniMaxWinInspectDb; + friend class MiniMaxWinCalcDb; public: - /*** typedefines ***************************************************************************************************************************/ - typedef unsigned char TwoBit; // 2-Bit variable ranging from 0 to 3 - typedef unsigned short PlyInfoVarType; // 2 Bytes for saving the ply info - typedef unsigned char CountArrayVarType; // 1 Byte for counting predesseccors - typedef unsigned int StateNumberVarType; // 4 Bytes for addressing states within a layer + /*** typedefines ***************************************************************************************************************************/ + typedef unsigned char TwoBit; // 2-Bit variable ranging from 0 to 3 + typedef unsigned short PlyInfoVarType; // 2 Bytes for saving the ply info + typedef unsigned char CountArrayVarType; // 1 Byte for counting predesseccors + typedef unsigned int StateNumberVarType; // 4 Bytes for addressing states within a layer - /*** protected structures ********************************************************************************************************************/ + /*** protected structures ********************************************************************************************************************/ - struct SkvFileHeader // header of the short knot value file - { - bool completed; // true if all states have been calculated - unsigned int numLayers; // number of layers - unsigned int headerCode; // = SKV_FILE_HEADER_CODE - unsigned int headerAndStatsSize; // size in bytes of this struct plus the stats - }; + struct SkvFileHeader // header of the short knot value file + { + bool completed; // true if all states have been calculated + unsigned int numLayers; // number of layers + unsigned int headerCode; // = SKV_FILE_HEADER_CODE + unsigned int headerAndStatsSize; // size in bytes of this struct plus the stats + }; - struct PlyInfoFileHeader - { - bool plyInfoCompleted; // true if ply innformation has been calculated for all game states - unsigned int numLayers; // number of layers - unsigned int headerCode; // = PLYINFO_HEADER_CODE - unsigned int headerAndPlyInfosSize; // size in bytes of this struct plus ... - }; + struct PlyInfoFileHeader + { + bool plyInfoCompleted; // true if ply innformation has been calculated for all game states + unsigned int numLayers; // number of layers + unsigned int headerCode; // = PLYINFO_HEADER_CODE + unsigned int headerAndPlyInfosSize; // size in bytes of this struct plus ... + }; - struct PlyInfo // this struct is created for each layer - { - bool plyInfoIsLoaded; // the array plyInfo[] exists in memory. does not necessary mean that it contains only valid values - bool plyInfoIsCompletedAndInFile; // the array plyInfo[] contains only fully calculated valid values - long long layerOffset; // position of this struct in the ply info file - unsigned int sizeInBytes; // size of this struct plus the array plyInfo[] - StateNumberVarType knotsInLayer; // number of knots of the corresponding layer - PlyInfoVarType *plyInfo; // array of size [knotsInLayer] containing the ply info for each knot in this layer - // compressorClass::compressedArrayClass * plyInfoCompressed; // compressed array containing the ply info for each knot in this layer - void *plyInfoCompressed; // dummy pointer for padding - }; + struct PlyInfo // this struct is created for each layer + { + bool plyInfoIsLoaded; // the array plyInfo[] exists in memory. does not necessary mean that it contains only valid values + bool plyInfoIsCompletedAndInFile; // the array plyInfo[] contains only fully calculated valid values + long long layerOffset; // position of this struct in the ply info file + unsigned int sizeInBytes; // size of this struct plus the array plyInfo[] + StateNumberVarType knotsInLayer; // number of knots of the corresponding layer + PlyInfoVarType *plyInfo; // array of size [knotsInLayer] containing the ply info for each knot in this layer + // compressorClass::compressedArrayClass * plyInfoCompressed; // compressed array containing the ply info for each knot in this layer + void *plyInfoCompressed; // dummy pointer for padding + }; - struct LayerStats - { - bool layerIsLoaded; // the array shortKnotValueByte[] exists in memory. does not necessary mean that it contains only valid values - bool layerIsCompletedAndInFile; // the array shortKnotValueByte[] contains only fully calculated valid values - long long layerOffset; // position of this struct in the short knot value file - unsigned int numSuccLayers; // number of succeding layers. states of other layers are connected by a move of a player - unsigned int succLayers[MAX_NUM_PRED_LAYERS]; // array containg the layer ids of the succeding layers - unsigned int partnerLayer; // layer id relevant when switching current and opponent player - StateNumberVarType knotsInLayer; // number of knots of the corresponding layer - StateNumberVarType numWonStates; // number of won states in this layer - StateNumberVarType numLostStates; // number of lost states in this layer - StateNumberVarType numDrawnStates; // number of drawn states in this layer - StateNumberVarType numInvalidStates; // number of invalid states in this layer - unsigned int sizeInBytes; // (knotsInLayer + 3) / 4 - TwoBit *shortKnotValueByte; // array of size [sizeInBytes] containg the short knot values - //compressorClass::compressedArrayClass * skvCompressed; // compressed array containing the short knot values - void *skvCompressed; // dummy pointer for padding - }; + struct LayerStats + { + bool layerIsLoaded; // the array shortKnotValueByte[] exists in memory. does not necessary mean that it contains only valid values + bool layerIsCompletedAndInFile; // the array shortKnotValueByte[] contains only fully calculated valid values + long long layerOffset; // position of this struct in the short knot value file + unsigned int numSuccLayers; // number of succeding layers. states of other layers are connected by a move of a player + unsigned int succLayers[MAX_NUM_PRED_LAYERS]; // array containg the layer ids of the succeding layers + unsigned int partnerLayer; // layer id relevant when switching current and opponent player + StateNumberVarType knotsInLayer; // number of knots of the corresponding layer + StateNumberVarType numWonStates; // number of won states in this layer + StateNumberVarType numLostStates; // number of lost states in this layer + StateNumberVarType numDrawnStates; // number of drawn states in this layer + StateNumberVarType numInvalidStates; // number of invalid states in this layer + unsigned int sizeInBytes; // (knotsInLayer + 3) / 4 + TwoBit *shortKnotValueByte; // array of size [sizeInBytes] containg the short knot values + //compressorClass::compressedArrayClass * skvCompressed; // compressed array containing the short knot values + void *skvCompressed; // dummy pointer for padding + }; - struct StateAdress - { - StateNumberVarType stateNumber; // state id within the corresponding layer - unsigned char layerNumber; // layer id - }; + struct StateAdress + { + StateNumberVarType stateNumber; // state id within the corresponding layer + unsigned char layerNumber; // layer id + }; - struct Node - { - bool isOpponentLevel; // the current considered knot belongs to an opponent game state - float floatValue; // Value of knot (for normal mode) - TwoBit shortValue; // Value of knot (for database) - unsigned int bestMoveId; // for calling class - unsigned int bestBranch; // branch with highest value - unsigned int numPossibilities; // number of branches - PlyInfoVarType plyInfo; // number of moves till win/lost - Node *branches; // pointer to branches - }; + struct Node + { + bool isOpponentLevel; // the current considered knot belongs to an opponent game state + float floatValue; // Value of knot (for normal mode) + TwoBit shortValue; // Value of knot (for database) + unsigned int bestMoveId; // for calling class + unsigned int bestBranch; // branch with highest value + unsigned int numPossibilities; // number of branches + PlyInfoVarType plyInfo; // number of moves till win/lost + Node *branches; // pointer to branches + }; - struct RetroAnalysisPredVars - { - unsigned int predStateNumbers; // - unsigned int predLayerNumbers; // - unsigned int predSymOperation; // - bool playerToMoveChanged; // - }; + struct RetroAnalysisPredVars + { + unsigned int predStateNumbers; // + unsigned int predLayerNumbers; // + unsigned int predSymOperation; // + bool playerToMoveChanged; // + }; - struct ArrayInfo - { - unsigned int type; // - long long sizeInBytes; // - long long compressedSizeInBytes; // - unsigned int belongsToLayer; // - unsigned int updateCounter; + struct ArrayInfo + { + unsigned int type; // + long long sizeInBytes; // + long long compressedSizeInBytes; // + unsigned int belongsToLayer; // + unsigned int updateCounter; - static const unsigned int arrayType_invalid = 0; - static const unsigned int arrayType_knotAlreadyCalculated = 1; - static const unsigned int arrayType_countArray = 2; - static const unsigned int arrayType_plyInfos = 3; - static const unsigned int arrayType_layerStats = 4; - static const unsigned int numArrayTypes = 5; + static const unsigned int arrayType_invalid = 0; + static const unsigned int arrayType_knotAlreadyCalculated = 1; + static const unsigned int arrayType_countArray = 2; + static const unsigned int arrayType_plyInfos = 3; + static const unsigned int arrayType_layerStats = 4; + static const unsigned int numArrayTypes = 5; - static const unsigned int updateCounterThreshold = 100; - }; + static const unsigned int updateCounterThreshold = 100; + }; - struct ArrayInfoChange - { - unsigned int itemIndex; // - ArrayInfo *arrayInfo; // - }; + struct ArrayInfoChange + { + unsigned int itemIndex; // + ArrayInfo *arrayInfo; // + }; - struct ArrayInfoContainer - { - MiniMax *c; - list arrayInfosToBeUpdated; // - list listArrays; // [itemIndex] - vector::iterator> vectorArrays; // [layerNumber*ArrayInfo::numArrayTypes + type] + struct ArrayInfoContainer + { + MiniMax *c; + list arrayInfosToBeUpdated; // + list listArrays; // [itemIndex] + vector::iterator> vectorArrays; // [layerNumber*ArrayInfo::numArrayTypes + type] - void addArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize); - void removeArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize); - void updateArray(unsigned int layerNumber, unsigned int type); - }; + void addArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize); + void removeArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize); + void updateArray(unsigned int layerNumber, unsigned int type); + }; - /*** public functions ***************************************************************************************************************************/ + /*** public functions ***************************************************************************************************************************/ - // Constructor / destructor - MiniMax(); - ~MiniMax(); + // Constructor / destructor + MiniMax(); + ~MiniMax(); - // Testing functions - bool testState(unsigned int layerNumber, unsigned int stateNumber); - bool testLayer(unsigned int layerNumber); - bool testIfSymStatesHaveSameValue(unsigned int layerNumber); - bool testSetSituationAndGetPoss(unsigned int layerNumber); + // Testing functions + bool testState(unsigned int layerNumber, unsigned int stateNumber); + bool testLayer(unsigned int layerNumber); + bool testIfSymStatesHaveSameValue(unsigned int layerNumber); + bool testSetSituationAndGetPoss(unsigned int layerNumber); - // Statistics - bool calcLayerStatistics(char *statisticsFileName); - void showMemoryStatus(); - unsigned int getNumThreads(); - bool anyFreshlyCalculatedLayer(); - unsigned int getLastCalculatedLayer(); - StateNumberVarType getNumWonStates(unsigned int layerNum); - StateNumberVarType getNumLostStates(unsigned int layerNum); - StateNumberVarType getNumDrawnStates(unsigned int layerNum); - StateNumberVarType getNumInvalidStates(unsigned int layerNum); - bool isLayerInDatabase(unsigned int layerNum); - long long getLayerSizeInBytes(unsigned int layerNum); - void setOutputStream(ostream *theStream, void (*printFunc)(void *pUserData), void *pUserData); - bool anyArrawInfoToUpdate(); - ArrayInfoChange getArrayInfoForUpdate(); - void getCurrentCalculatedLayer(vector &layers); - LPWSTR getCurrentActionStr(); + // Statistics + bool calcLayerStatistics(char *statisticsFileName); + void showMemoryStatus(); + unsigned int getNumThreads(); + bool anyFreshlyCalculatedLayer(); + unsigned int getLastCalculatedLayer(); + StateNumberVarType getNumWonStates(unsigned int layerNum); + StateNumberVarType getNumLostStates(unsigned int layerNum); + StateNumberVarType getNumDrawnStates(unsigned int layerNum); + StateNumberVarType getNumInvalidStates(unsigned int layerNum); + bool isLayerInDatabase(unsigned int layerNum); + long long getLayerSizeInBytes(unsigned int layerNum); + void setOutputStream(ostream *theStream, void (*printFunc)(void *pUserData), void *pUserData); + bool anyArrawInfoToUpdate(); + ArrayInfoChange getArrayInfoForUpdate(); + void getCurrentCalculatedLayer(vector &layers); + LPWSTR getCurrentActionStr(); - // Main function for getting the best choice - void *getBestChoice(unsigned int tilLevel, unsigned int *choice, unsigned int maximumNumberOfBranches); + // Main function for getting the best choice + void *getBestChoice(unsigned int tilLevel, unsigned int *choice, unsigned int maximumNumberOfBranches); - // Database functions - bool openDatabase(const char *directory, unsigned int maximumNumberOfBranches); - void calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLayer); - bool isCurrentStateInDatabase(unsigned int threadNo); - void closeDatabase(); - void unloadAllLayers(); - void unloadAllPlyInfos(); - void pauseDatabaseCalculation(); - void cancelDatabaseCalculation(); - bool wasDatabaseCalculationCancelled(); + // Database functions + bool openDatabase(const char *directory, unsigned int maximumNumberOfBranches); + void calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLayer); + bool isCurrentStateInDatabase(unsigned int threadNo); + void closeDatabase(); + void unloadAllLayers(); + void unloadAllPlyInfos(); + void pauseDatabaseCalculation(); + void cancelDatabaseCalculation(); + bool wasDatabaseCalculationCancelled(); - // Virtual Functions - virtual void prepareBestChoiceCalculation() - { - while (true) - ; - }; // is called once before building the tree - virtual unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities) - { - while (true) - ; - return 0; - }; // returns a pointer to the possibility-IDs - virtual void deletePossibilities(unsigned int threadNo, void *pPossibilities) - { - while (true) - ; - }; - 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) - { - while (true) - ; - }; - virtual void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities) - { - while (true) - ; - }; + // Virtual Functions + virtual void prepareBestChoiceCalculation() + { + while (true) + ; + }; // is called once before building the tree + virtual unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities) + { + while (true) + ; + return 0; + }; // returns a pointer to the possibility-IDs + virtual void deletePossibilities(unsigned int threadNo, void *pPossibilities) + { + while (true) + ; + }; + 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) + { + while (true) + ; + }; + virtual void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities) + { + while (true) + ; + }; - virtual bool shallRetroAnalysisBeUsed(unsigned int layerNum) - { - return false; - }; - virtual unsigned int getNumberOfLayers() - { - while (true) - ; - return 0; - }; - virtual unsigned int getNumberOfKnotsInLayer(unsigned int layerNum) - { - while (true) - ; - return 0; - }; - virtual void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers) - { - while (true) - ; - }; - virtual unsigned int getPartnerLayer(unsigned int layerNum) - { - while (true) - ; - return 0; - }; - virtual string getOutputInformation(unsigned int layerNum) - { - while (true) - ; - return string(""); - }; + virtual bool shallRetroAnalysisBeUsed(unsigned int layerNum) + { + return false; + }; + virtual unsigned int getNumberOfLayers() + { + while (true) + ; + return 0; + }; + virtual unsigned int getNumberOfKnotsInLayer(unsigned int layerNum) + { + while (true) + ; + return 0; + }; + virtual void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers) + { + while (true) + ; + }; + virtual unsigned int getPartnerLayer(unsigned int layerNum) + { + while (true) + ; + return 0; + }; + virtual string getOutputInformation(unsigned int layerNum) + { + while (true) + ; + return string(""); + }; - virtual void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel) - { - while (true) - ; - }; - virtual bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) - { - while (true) - ; - return false; - }; + virtual void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel) + { + while (true) + ; + }; + virtual bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) + { + while (true) + ; + return false; + }; - virtual void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue) - { - while (true) - ; - }; // value of situation for the initial current player - virtual bool getOpponentLevel(unsigned int threadNo) - { - while (true) - ; - return false; - }; - virtual unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber) - { - while (true) - ; - return 0; - }; - virtual unsigned int getLayerNumber(unsigned int threadNo) - { - while (true) - ; - return 0; - }; - virtual void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers) - { - while (true) - ; - }; - virtual void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars) - { - while (true) - ; - }; + virtual void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue) + { + while (true) + ; + }; // value of situation for the initial current player + virtual bool getOpponentLevel(unsigned int threadNo) + { + while (true) + ; + return false; + }; + virtual unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber) + { + while (true) + ; + return 0; + }; + virtual unsigned int getLayerNumber(unsigned int threadNo) + { + while (true) + ; + return 0; + }; + virtual void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers) + { + while (true) + ; + }; + virtual void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars) + { + while (true) + ; + }; - virtual void printBoard(unsigned int threadNo, unsigned char value) - { - while (true) - ; - }; - virtual void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities) - { - while (true) - ; - }; + virtual void printBoard(unsigned int threadNo, unsigned char value) + { + while (true) + ; + }; + virtual void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities) + { + while (true) + ; + }; - virtual void prepareDatabaseCalculation() - { - while (true) - ; - }; - virtual void wrapUpDatabaseCalculation(bool calculationAborted) - { - while (true) - ; - }; + virtual void prepareDatabaseCalculation() + { + while (true) + ; + }; + virtual void wrapUpDatabaseCalculation(bool calculationAborted) + { + while (true) + ; + }; private: - /*** classes for testing ********************************************************************************************************************/ + /*** classes for testing ********************************************************************************************************************/ - struct TestLayersVars - { - MiniMax *pMiniMax; - unsigned int curThreadNo; - unsigned int layerNumber; - LONGLONG statesProcessed; - TwoBit *subValueInDatabase; - PlyInfoVarType *subPlyInfos; - bool *hasCurPlayerChanged; - }; + struct TestLayersVars + { + MiniMax *pMiniMax; + unsigned int curThreadNo; + unsigned int layerNumber; + LONGLONG statesProcessed; + TwoBit *subValueInDatabase; + PlyInfoVarType *subPlyInfos; + bool *hasCurPlayerChanged; + }; - /*** classes for the alpha beta algorithmn ********************************************************************************************************************/ + /*** classes for the alpha beta algorithmn ********************************************************************************************************************/ - struct AlphaBetaThreadVars // thread specific variables for each thread in the alpha beta algorithmn - { - long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed - unsigned int threadNo; - }; + struct AlphaBetaThreadVars // thread specific variables for each thread in the alpha beta algorithmn + { + long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed + unsigned int threadNo; + }; - struct AlphaBetaGlobalVars // constant during calculation - { - unsigned int layerNumber; // layer number of the current process layer - long long totalNumKnots; // total numbers of knots which have to be stored in memory - long long numKnotsToCalc; // number of knots of all layers to be calculated - vector thread; - unsigned int statsValueCounter[SKV_NUM_VALUES]; - MiniMax *pMiniMax; + struct AlphaBetaGlobalVars // constant during calculation + { + unsigned int layerNumber; // layer number of the current process layer + long long totalNumKnots; // total numbers of knots which have to be stored in memory + long long numKnotsToCalc; // number of knots of all layers to be calculated + vector thread; + unsigned int statsValueCounter[SKV_NUM_VALUES]; + MiniMax *pMiniMax; - AlphaBetaGlobalVars(MiniMax *pMiniMax, unsigned int layerNumber) - { - this->thread.resize(pMiniMax->threadManager.getNumThreads()); - for (unsigned int threadNo = 0; threadNo < pMiniMax->threadManager.getNumThreads(); threadNo++) - { - this->thread[threadNo].numStatesToProcess = 0; - this->thread[threadNo].threadNo = threadNo; - } - this->layerNumber = layerNumber; - this->pMiniMax = pMiniMax; - if (pMiniMax->layerStats) - { - this->numKnotsToCalc = pMiniMax->layerStats[layerNumber].knotsInLayer; - this->totalNumKnots = pMiniMax->layerStats[layerNumber].knotsInLayer; - } - this->statsValueCounter[SKV_VALUE_GAME_WON] = 0; - this->statsValueCounter[SKV_VALUE_GAME_LOST] = 0; - this->statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; - this->statsValueCounter[SKV_VALUE_INVALID] = 0; - } - }; + AlphaBetaGlobalVars(MiniMax *pMiniMax, unsigned int layerNumber) + { + this->thread.resize(pMiniMax->threadManager.getNumThreads()); + for (unsigned int threadNo = 0; threadNo < pMiniMax->threadManager.getNumThreads(); threadNo++) { + this->thread[threadNo].numStatesToProcess = 0; + this->thread[threadNo].threadNo = threadNo; + } + this->layerNumber = layerNumber; + this->pMiniMax = pMiniMax; + if (pMiniMax->layerStats) { + this->numKnotsToCalc = pMiniMax->layerStats[layerNumber].knotsInLayer; + this->totalNumKnots = pMiniMax->layerStats[layerNumber].knotsInLayer; + } + this->statsValueCounter[SKV_VALUE_GAME_WON] = 0; + this->statsValueCounter[SKV_VALUE_GAME_LOST] = 0; + this->statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; + this->statsValueCounter[SKV_VALUE_INVALID] = 0; + } + }; - struct AlphaBetaDefaultThreadVars - { - MiniMax *pMiniMax; - AlphaBetaGlobalVars *alphaBetaVars; - unsigned int layerNumber; - LONGLONG statesProcessed; - unsigned int statsValueCounter[SKV_NUM_VALUES]; + struct AlphaBetaDefaultThreadVars + { + MiniMax *pMiniMax; + AlphaBetaGlobalVars *alphaBetaVars; + unsigned int layerNumber; + LONGLONG statesProcessed; + unsigned int statsValueCounter[SKV_NUM_VALUES]; - AlphaBetaDefaultThreadVars(){}; - AlphaBetaDefaultThreadVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) - { - this->statesProcessed = 0; - this->layerNumber = layerNumber; - this->pMiniMax = pMiniMax; - this->alphaBetaVars = alphaBetaVars; - for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) - { - this->statsValueCounter[curStateValue] = 0; - } - }; - void reduceDefault() - { - pMiniMax->numStatesProcessed += this->statesProcessed; - for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) - { - alphaBetaVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; - } - }; - }; + AlphaBetaDefaultThreadVars() + { + }; + AlphaBetaDefaultThreadVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) + { + this->statesProcessed = 0; + this->layerNumber = layerNumber; + this->pMiniMax = pMiniMax; + this->alphaBetaVars = alphaBetaVars; + for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) { + this->statsValueCounter[curStateValue] = 0; + } + }; + void reduceDefault() + { + pMiniMax->numStatesProcessed += this->statesProcessed; + for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) { + alphaBetaVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; + } + }; + }; - struct InitAlphaBetaVars : public ThreadManager::ThreadVarsArrayItem, public AlphaBetaDefaultThreadVars - { - BufferedFile *bufferedFile; - bool initAlreadyDone; + struct InitAlphaBetaVars : public ThreadManager::ThreadVarsArrayItem, public AlphaBetaDefaultThreadVars + { + BufferedFile *bufferedFile; + bool initAlreadyDone; - InitAlphaBetaVars(){}; - InitAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) - { - this->bufferedFile = initArray; - this->initAlreadyDone = initAlreadyDone; - }; - void initializeElement(InitAlphaBetaVars &master) - { - *this = master; - }; - void reduce() - { - reduceDefault(); - }; - }; + InitAlphaBetaVars() + { + }; + InitAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) + { + this->bufferedFile = initArray; + this->initAlreadyDone = initAlreadyDone; + }; + void initializeElement(InitAlphaBetaVars &master) + { + *this = master; + }; + void reduce() + { + reduceDefault(); + }; + }; - struct RunAlphaBetaVars : public ThreadManager::ThreadVarsArrayItem, public AlphaBetaDefaultThreadVars - { - Node *branchArray = nullptr; // array of size [(depthOfFullTree - tilLevel) * maxNumBranches] for storage of the branches at each search depth - unsigned int *freqValuesSubMovesBranchWon = nullptr; // ... - unsigned int freqValuesSubMoves[4]; // ... + struct RunAlphaBetaVars : public ThreadManager::ThreadVarsArrayItem, public AlphaBetaDefaultThreadVars + { + Node *branchArray = nullptr; // array of size [(depthOfFullTree - tilLevel) * maxNumBranches] for storage of the branches at each search depth + unsigned int *freqValuesSubMovesBranchWon = nullptr; // ... + unsigned int freqValuesSubMoves[4]; // ... - RunAlphaBetaVars(){}; - RunAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) - { - initializeElement(*this); - }; - ~RunAlphaBetaVars() - { - SAFE_DELETE_ARRAY(branchArray); - SAFE_DELETE_ARRAY(freqValuesSubMovesBranchWon); - } - void reduce() - { - reduceDefault(); - }; - void initializeElement(RunAlphaBetaVars &master) - { - *this = master; - branchArray = new Node[alphaBetaVars->pMiniMax->maxNumBranches * alphaBetaVars->pMiniMax->depthOfFullTree]; - freqValuesSubMovesBranchWon = new unsigned int[alphaBetaVars->pMiniMax->maxNumBranches]; - }; - }; + RunAlphaBetaVars() + { + }; + RunAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber) + { + initializeElement(*this); + }; + ~RunAlphaBetaVars() + { + SAFE_DELETE_ARRAY(branchArray); + SAFE_DELETE_ARRAY(freqValuesSubMovesBranchWon); + } + void reduce() + { + reduceDefault(); + }; + void initializeElement(RunAlphaBetaVars &master) + { + *this = master; + branchArray = new Node[alphaBetaVars->pMiniMax->maxNumBranches * alphaBetaVars->pMiniMax->depthOfFullTree]; + freqValuesSubMovesBranchWon = new unsigned int[alphaBetaVars->pMiniMax->maxNumBranches]; + }; + }; - /*** classes for the retro analysis ***************************************************************************************************************************/ + /*** classes for the retro analysis ***************************************************************************************************************************/ - struct RetroAnalysisQueueState - { - StateNumberVarType stateNumber; // state stored in the retro analysis queue. the queue is a buffer containing states to be passed to 'RetroAnalysisThreadVars::statesToProcess' - PlyInfoVarType numPliesTillCurState; // ply number for the stored state - }; + struct RetroAnalysisQueueState + { + StateNumberVarType stateNumber; // state stored in the retro analysis queue. the queue is a buffer containing states to be passed to 'RetroAnalysisThreadVars::statesToProcess' + PlyInfoVarType numPliesTillCurState; // ply number for the stored state + }; - struct RetroAnalysisThreadVars // thread specific variables for each thread in the retro analysis - { - vector statesToProcess; // vector-queue containing the states, whose short knot value are known for sure. they have to be processed. if processed the state will be removed from list. indexing: [threadNo][plyNumber] - vector> stateQueue; // Queue containing states, whose 'count value' shall be increased by one. Before writing 'count value' to 'count array' the writing positions are sorted for faster processing. - long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed - unsigned int threadNo; - }; + struct RetroAnalysisThreadVars // thread specific variables for each thread in the retro analysis + { + vector statesToProcess; // vector-queue containing the states, whose short knot value are known for sure. they have to be processed. if processed the state will be removed from list. indexing: [threadNo][plyNumber] + vector> stateQueue; // Queue containing states, whose 'count value' shall be increased by one. Before writing 'count value' to 'count array' the writing positions are sorted for faster processing. + long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed + unsigned int threadNo; + }; - struct retroAnalysisGlobalVars // constant during calculation - { - vector countArrays; // One count array for each layer in 'layersToCalculate'. (For the nine men's morris game two layers have to considered at once.) - vector layerInitialized; // - vector layersToCalculate; // layers which shall be calculated - long long totalNumKnots; // total numbers of knots which have to be stored in memory - long long numKnotsToCalc; // number of knots of all layers to be calculated - vector thread; - unsigned int statsValueCounter[SKV_NUM_VALUES]; - MiniMax *pMiniMax; - }; + struct retroAnalysisGlobalVars // constant during calculation + { + vector countArrays; // One count array for each layer in 'layersToCalculate'. (For the nine men's morris game two layers have to considered at once.) + vector layerInitialized; // + vector layersToCalculate; // layers which shall be calculated + long long totalNumKnots; // total numbers of knots which have to be stored in memory + long long numKnotsToCalc; // number of knots of all layers to be calculated + vector thread; + unsigned int statsValueCounter[SKV_NUM_VALUES]; + MiniMax *pMiniMax; + }; - struct RetroAnalysisDefaultThreadVars - { - MiniMax *pMiniMax; - retroAnalysisGlobalVars *retroVars; - unsigned int layerNumber; - LONGLONG statesProcessed; - unsigned int statsValueCounter[SKV_NUM_VALUES]; + struct RetroAnalysisDefaultThreadVars + { + MiniMax *pMiniMax; + retroAnalysisGlobalVars *retroVars; + unsigned int layerNumber; + LONGLONG statesProcessed; + unsigned int statsValueCounter[SKV_NUM_VALUES]; - RetroAnalysisDefaultThreadVars(){}; - RetroAnalysisDefaultThreadVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) - { - this->statesProcessed = 0; - this->layerNumber = layerNumber; - this->pMiniMax = pMiniMax; - this->retroVars = retroVars; - for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) - { - this->statsValueCounter[curStateValue] = 0; - } - }; - void reduceDefault() - { - pMiniMax->numStatesProcessed += this->statesProcessed; - for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) - { - retroVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; - } - }; - }; + RetroAnalysisDefaultThreadVars() + { + }; + RetroAnalysisDefaultThreadVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) + { + this->statesProcessed = 0; + this->layerNumber = layerNumber; + this->pMiniMax = pMiniMax; + this->retroVars = retroVars; + for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) { + this->statsValueCounter[curStateValue] = 0; + } + }; + void reduceDefault() + { + pMiniMax->numStatesProcessed += this->statesProcessed; + for (unsigned int curStateValue = 0; curStateValue < SKV_NUM_VALUES; curStateValue++) { + retroVars->statsValueCounter[curStateValue] += this->statsValueCounter[curStateValue]; + } + }; + }; - struct InitRetroAnalysisVars : public ThreadManager::ThreadVarsArrayItem, public RetroAnalysisDefaultThreadVars - { - BufferedFile *bufferedFile; - bool initAlreadyDone; + struct InitRetroAnalysisVars : public ThreadManager::ThreadVarsArrayItem, public RetroAnalysisDefaultThreadVars + { + BufferedFile *bufferedFile; + bool initAlreadyDone; - InitRetroAnalysisVars(){}; - InitRetroAnalysisVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber) - { - this->bufferedFile = initArray; - this->initAlreadyDone = initAlreadyDone; - }; - void initializeElement(InitRetroAnalysisVars &master) - { - *this = master; - }; - void reduce() - { - reduceDefault(); - }; - }; + InitRetroAnalysisVars() + { + }; + InitRetroAnalysisVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber) + { + this->bufferedFile = initArray; + this->initAlreadyDone = initAlreadyDone; + }; + void initializeElement(InitRetroAnalysisVars &master) + { + *this = master; + }; + void reduce() + { + reduceDefault(); + }; + }; - struct AddNumSuccedorsVars : public ThreadManager::ThreadVarsArrayItem, public RetroAnalysisDefaultThreadVars - { - RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; + struct AddNumSuccedorsVars : public ThreadManager::ThreadVarsArrayItem, public RetroAnalysisDefaultThreadVars + { + RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; - AddNumSuccedorsVars(){}; - AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber){}; - void initializeElement(AddNumSuccedorsVars &master) - { - *this = master; - }; - void reduce() - { - reduceDefault(); - }; - }; + AddNumSuccedorsVars() + { + }; + AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber) + { + }; + void initializeElement(AddNumSuccedorsVars &master) + { + *this = master; + }; + void reduce() + { + reduceDefault(); + }; + }; - /*** private variables ***************************************************************************************************************************/ + /*** private variables ***************************************************************************************************************************/ - // variables, which are constant during database calculation - int verbosity = 2; // output detail level. default is 2 - unsigned char skvPerspectiveMatrix[4][2]; // [short knot value][current or opponent player] - A winning situation is a loosing situation for the opponent and so on ... - bool calcDatabase = false; // true, if the database is currently beeing calculated - HANDLE hFileShortKnotValues = nullptr; // handle of the file for the short knot value - HANDLE hFilePlyInfo = nullptr; // handle of the file for the ply info - SkvFileHeader skvfHeader; // short knot value file header - PlyInfoFileHeader plyInfoHeader; // header of the ply info file - string fileDirectory; // path of the folder where the database files are located - ostream *osPrint = nullptr; // stream for output. default is cout - list lastCalculatedLayer; // - vector layersToCalculate; // used in calcLayer() and getCurrentCalculatedLayers() - bool onlyPrepareLayer = false; // - bool stopOnCriticalError = true; // if true then process will stay in while loop - ThreadManager threadManager; // - CRITICAL_SECTION csDatabase; // - CRITICAL_SECTION csOsPrint; // for thread safety when output is passed to osPrint - void (*userPrintFunc)(void *) = nullptr; // called every time output is passed to osPrint - void *pDataForUserPrintFunc = nullptr; // pointer passed when calling userPrintFunc - ArrayInfoContainer arrayInfos; // information about the arrays in memory + // variables, which are constant during database calculation + int verbosity = 2; // output detail level. default is 2 + unsigned char skvPerspectiveMatrix[4][2]; // [short knot value][current or opponent player] - A winning situation is a loosing situation for the opponent and so on ... + bool calcDatabase = false; // true, if the database is currently beeing calculated + HANDLE hFileShortKnotValues = nullptr; // handle of the file for the short knot value + HANDLE hFilePlyInfo = nullptr; // handle of the file for the ply info + SkvFileHeader skvfHeader; // short knot value file header + PlyInfoFileHeader plyInfoHeader; // header of the ply info file + string fileDirectory; // path of the folder where the database files are located + ostream *osPrint = nullptr; // stream for output. default is cout + list lastCalculatedLayer; // + vector layersToCalculate; // used in calcLayer() and getCurrentCalculatedLayers() + bool onlyPrepareLayer = false; // + bool stopOnCriticalError = true; // if true then process will stay in while loop + ThreadManager threadManager; // + CRITICAL_SECTION csDatabase; // + CRITICAL_SECTION csOsPrint; // for thread safety when output is passed to osPrint + void (*userPrintFunc)(void *) = nullptr; // called every time output is passed to osPrint + void *pDataForUserPrintFunc = nullptr; // pointer passed when calling userPrintFunc + ArrayInfoContainer arrayInfos; // information about the arrays in memory - // thread specific or non-constant variables - LONGLONG memoryUsed2 = 0; // memory in bytes used for storing: ply information, short knot value and ... - LONGLONG numStatesProcessed = 0; // - unsigned int maxNumBranches = 0; // maximum number of branches/moves - unsigned int depthOfFullTree = 0; // maxumim search depth - unsigned int curCalculatedLayer = 0; // id of the currently calculated layer - unsigned int curCalculationActionId = 0; // one of ... - bool layerInDatabase = false; // true if the current considered layer has already been calculated and stored in the database - void *pRootPossibilities = nullptr; // pointer to the structure passed by getPossibilities() for the state at which getBestChoice() has been called - LayerStats *layerStats = nullptr; // array of size [] containing general layer information and the skv of all layers - PlyInfo *plyInfos = nullptr; // array of size [] containing ply information + // thread specific or non-constant variables + LONGLONG memoryUsed2 = 0; // memory in bytes used for storing: ply information, short knot value and ... + LONGLONG numStatesProcessed = 0; // + unsigned int maxNumBranches = 0; // maximum number of branches/moves + unsigned int depthOfFullTree = 0; // maxumim search depth + unsigned int curCalculatedLayer = 0; // id of the currently calculated layer + unsigned int curCalculationActionId = 0; // one of ... + bool layerInDatabase = false; // true if the current considered layer has already been calculated and stored in the database + void *pRootPossibilities = nullptr; // pointer to the structure passed by getPossibilities() for the state at which getBestChoice() has been called + LayerStats *layerStats = nullptr; // array of size [] containing general layer information and the skv of all layers + PlyInfo *plyInfos = nullptr; // array of size [] containing ply information - // variables concerning the compression of the database - // compressorClass * compressor = nullptr; - // unsigned int compressionAlgorithmnId = 0; // 0 or one of the COMPRESSOR_ALG_... constants + // variables concerning the compression of the database + // compressorClass * compressor = nullptr; + // unsigned int compressionAlgorithmnId = 0; // 0 or one of the COMPRESSOR_ALG_... constants - // database io operations per second - long long numReadSkvOperations = 0; // number of read operations done since start of the programm - long long numWriteSkvOperations = 0; // number of write operations done since start of the programm - long long numReadPlyOperations = 0; // number of read operations done since start of the programm - long long numWritePlyOperations = 0; // number of write operations done since start of the programm - LARGE_INTEGER readSkvInterval; // time of interval for read operations - LARGE_INTEGER writeSkvInterval; // '' - LARGE_INTEGER readPlyInterval; // '' - LARGE_INTEGER writePlyInterval; // '' - LARGE_INTEGER frequency; // performance-counter frequency, in counts per second + // database io operations per second + long long numReadSkvOperations = 0; // number of read operations done since start of the programm + long long numWriteSkvOperations = 0; // number of write operations done since start of the programm + long long numReadPlyOperations = 0; // number of read operations done since start of the programm + long long numWritePlyOperations = 0; // number of write operations done since start of the programm + LARGE_INTEGER readSkvInterval; // time of interval for read operations + LARGE_INTEGER writeSkvInterval; // '' + LARGE_INTEGER readPlyInterval; // '' + LARGE_INTEGER writePlyInterval; // '' + LARGE_INTEGER frequency; // performance-counter frequency, in counts per second - /*** private functions ***************************************************************************************************************************/ + /*** private functions ***************************************************************************************************************************/ - // database functions - void openSkvFile(const char *path, unsigned int maximumNumberOfBranches); - void openPlyInfoFile(const char *path); - bool calcLayer(unsigned int layerNumber); - void unloadPlyInfo(unsigned int layerNumber); - void unloadLayer(unsigned int layerNumber); - void saveHeader(SkvFileHeader *dbH, LayerStats *lStats); - void saveHeader(PlyInfoFileHeader *piH, PlyInfo *pInfo); - void readKnotValueFromDatabase(unsigned int threadNo, unsigned int &layerNumber, unsigned int &stateNumber, TwoBit &knotValue, bool &invalidLayerOrStateNumber, bool &layerInDatabaseAndCompleted); - void readKnotValueFromDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit &knotValue); - void readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType &value); - void saveKnotValueInDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue); - void savePlyInfoInDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType value); - void loadBytesFromFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes); - void saveBytesToFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes); - void saveLayerToFile(unsigned int layerNumber); - inline void measureIops(long long &numOperations, LARGE_INTEGER &interval, LARGE_INTEGER &curTimeBefore, char text[]); + // database functions + void openSkvFile(const char *path, unsigned int maximumNumberOfBranches); + void openPlyInfoFile(const char *path); + bool calcLayer(unsigned int layerNumber); + void unloadPlyInfo(unsigned int layerNumber); + void unloadLayer(unsigned int layerNumber); + void saveHeader(SkvFileHeader *dbH, LayerStats *lStats); + void saveHeader(PlyInfoFileHeader *piH, PlyInfo *pInfo); + void readKnotValueFromDatabase(unsigned int threadNo, unsigned int &layerNumber, unsigned int &stateNumber, TwoBit &knotValue, bool &invalidLayerOrStateNumber, bool &layerInDatabaseAndCompleted); + void readKnotValueFromDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit &knotValue); + void readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType &value); + void saveKnotValueInDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue); + void savePlyInfoInDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType value); + void loadBytesFromFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes); + void saveBytesToFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes); + void saveLayerToFile(unsigned int layerNumber); + inline void measureIops(long long &numOperations, LARGE_INTEGER &interval, LARGE_INTEGER &curTimeBefore, char text[]); - // Testing functions - static DWORD testLayerThreadProc(void *pParameter, int index); - static DWORD testSetSituationThreadProc(void *pParameter, int index); + // Testing functions + static DWORD testLayerThreadProc(void *pParameter, int index); + static DWORD testSetSituationThreadProc(void *pParameter, int index); - // Alpha-Beta-Algorithmn - bool calcKnotValuesByAlphaBeta(unsigned int layerNumber); - bool initAlphaBeta(AlphaBetaGlobalVars &retroVars); - bool runAlphaBeta(AlphaBetaGlobalVars &retroVars); - void letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, float alpha, float beta); - bool alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int &layerNumber, unsigned int &stateNumber); - void alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, void *pPossibilities, unsigned int &maxWonfreqValuesSubMoves, float &alpha, float &beta); - void alphaBetaCalcPlyInfo(Node *knot); - void alphaBetaCalcKnotValue(Node *knot); - void alphaBetaChooseBestMove(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, unsigned int maxWonfreqValuesSubMoves); - void alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue, PlyInfoVarType plyValue, bool invertValue); - static DWORD initAlphaBetaThreadProc(void *pParameter, int index); - static DWORD runAlphaBetaThreadProc(void *pParameter, int index); + // Alpha-Beta-Algorithmn + bool calcKnotValuesByAlphaBeta(unsigned int layerNumber); + bool initAlphaBeta(AlphaBetaGlobalVars &retroVars); + bool runAlphaBeta(AlphaBetaGlobalVars &retroVars); + void letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, float alpha, float beta); + bool alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int &layerNumber, unsigned int &stateNumber); + void alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, void *pPossibilities, unsigned int &maxWonfreqValuesSubMoves, float &alpha, float &beta); + void alphaBetaCalcPlyInfo(Node *knot); + void alphaBetaCalcKnotValue(Node *knot); + void alphaBetaChooseBestMove(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, unsigned int maxWonfreqValuesSubMoves); + void alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue, PlyInfoVarType plyValue, bool invertValue); + static DWORD initAlphaBetaThreadProc(void *pParameter, int index); + static DWORD runAlphaBetaThreadProc(void *pParameter, int index); - // Retro Analysis - bool calcKnotValuesByRetroAnalysis(vector &layersToCalculate); - bool initRetroAnalysis(retroAnalysisGlobalVars &retroVars); - bool prepareCountArrays(retroAnalysisGlobalVars &retroVars); - bool calcNumSuccedors(retroAnalysisGlobalVars &retroVars); - bool performRetroAnalysis(retroAnalysisGlobalVars &retroVars); - bool addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState); - static bool retroAnalysisQueueStateComp(const RetroAnalysisQueueState &a, const RetroAnalysisQueueState &b) - { - return a.stateNumber < b.stateNumber; - }; - static DWORD initRetroAnalysisThreadProc(void *pParameter, int index); - static DWORD addNumSuccedorsThreadProc(void *pParameter, int index); - static DWORD performRetroAnalysisThreadProc(void *pParameter); + // Retro Analysis + bool calcKnotValuesByRetroAnalysis(vector &layersToCalculate); + bool initRetroAnalysis(retroAnalysisGlobalVars &retroVars); + bool prepareCountArrays(retroAnalysisGlobalVars &retroVars); + bool calcNumSuccedors(retroAnalysisGlobalVars &retroVars); + bool performRetroAnalysis(retroAnalysisGlobalVars &retroVars); + bool addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState); + static bool retroAnalysisQueueStateComp(const RetroAnalysisQueueState &a, const RetroAnalysisQueueState &b) + { + return a.stateNumber < b.stateNumber; + }; + static DWORD initRetroAnalysisThreadProc(void *pParameter, int index); + static DWORD addNumSuccedorsThreadProc(void *pParameter, int index); + static DWORD performRetroAnalysisThreadProc(void *pParameter); - // Progress report functions - void showLayerStats(unsigned int layerNumber); - bool falseOrStop(); + // Progress report functions + void showLayerStats(unsigned int layerNumber); + bool falseOrStop(); }; #endif diff --git a/src/perfect/miniMaxAI.h b/src/perfect/miniMaxAI.h index adb59c2b..5d1bc271 100644 --- a/src/perfect/miniMaxAI.h +++ b/src/perfect/miniMaxAI.h @@ -1,9 +1,9 @@ /*********************************************************************\ - MiniMaxAI.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + MiniMaxAI.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef MINIMAXAI_H @@ -24,112 +24,126 @@ class MiniMaxAI : public MillAI, MiniMax { protected: - // structs - struct Possibility - { - unsigned int from[MAX_NUM_POS_MOVES]; - unsigned int to[MAX_NUM_POS_MOVES]; - }; + // structs + struct Possibility + { + unsigned int from[MAX_NUM_POS_MOVES]; + unsigned int to[MAX_NUM_POS_MOVES]; + }; - struct Backup - { - float value; - bool gameHasFinished; - bool settingPhase; - int fieldFrom, fieldTo; // value of board - unsigned int from, to; // index of board - unsigned int curNumStones, oppNumStones; - unsigned int curPosMoves, oppPosMoves; - unsigned int curMissStones, oppMissStones; - unsigned int stonesSet; - unsigned int stoneMustBeRemoved; - unsigned int stonePartOfMill[fieldStruct::size]; - unsigned int warnings[fieldStruct::size]; - Player *curPlayer, *oppPlayer; - }; + struct Backup + { + float value; + bool gameHasFinished; + bool settingPhase; + int fieldFrom, fieldTo; // value of board + unsigned int from, to; // index of board + unsigned int curNumStones, oppNumStones; + unsigned int curPosMoves, oppPosMoves; + unsigned int curMissStones, oppMissStones; + unsigned int stonesSet; + unsigned int stoneMustBeRemoved; + unsigned int stonePartOfMill[fieldStruct::size]; + unsigned int warnings[fieldStruct::size]; + Player *curPlayer, *oppPlayer; + }; - // Variables - fieldStruct *field; // pointer of the current board [changed by move()] - float currentValue; // value of current situation for board->currentPlayer - bool gameHasFinished; // someone has won or current board is full + // Variables + fieldStruct *field; // pointer of the current board [changed by move()] + float currentValue; // value of current situation for board->currentPlayer + bool gameHasFinished; // someone has won or current board is full - int ownId; // id of the player who called the play()-function - unsigned int curSearchDepth; // current level - unsigned int depthOfFullTree; // search depth where the whole tree is explored - unsigned int *idPossibilities; // returned pointer of getPossibilities()-function - Backup *oldStates; // for undo()-function - Possibility *possibilities; // for getPossNormalMove()-function + int ownId; // id of the player who called the play()-function + unsigned int curSearchDepth; // current level + unsigned int depthOfFullTree; // search depth where the whole tree is explored + unsigned int *idPossibilities; // returned pointer of getPossibilities()-function + Backup *oldStates; // for undo()-function + Possibility *possibilities; // for getPossNormalMove()-function - // Functions - unsigned int *getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities); - unsigned int *getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities); - unsigned int *getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities); + // Functions + unsigned int *getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities); + unsigned int *getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities); + unsigned int *getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities); - // move functions - inline void updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone); - inline void updateWarning(unsigned int firstStone, unsigned int secondStone); - inline void setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree); - inline void removeStone(unsigned int from, Backup *backup); - inline void setStone(unsigned int to, Backup *backup); - inline void normalMove(unsigned int from, unsigned int to, Backup *backup); + // move functions + inline void updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone); + inline void updateWarning(unsigned int firstStone, unsigned int secondStone); + inline void setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree); + inline void removeStone(unsigned int from, Backup *backup); + inline void setStone(unsigned int to, Backup *backup); + inline void normalMove(unsigned int from, unsigned int to, Backup *backup); - // Virtual Functions - void prepareBestChoiceCalculation(); - unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities); - void deletePossibilities(unsigned int threadNo, void *pPossibilities); - void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities); - void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities); - void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue); - void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities); + // Virtual Functions + void prepareBestChoiceCalculation(); + unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities); + void deletePossibilities(unsigned int threadNo, void *pPossibilities); + void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities); + void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities); + void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue); + void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities); - unsigned int getNumberOfLayers() - { - return 0; - }; - unsigned int getNumberOfKnotsInLayer(unsigned int layerNum) - { - return 0; - }; - void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers){}; - unsigned int getPartnerLayer(unsigned int layerNum) - { - return 0; - }; - string getOutputInformation(unsigned int layerNum) - { - return string(""); - }; - void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel){}; - bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) - { - return false; - }; - bool getOpponentLevel(unsigned int threadNo) - { - return false; - }; - unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber) - { - return 0; - }; - unsigned int getLayerNumber(unsigned int threadNo) - { - return 0; - }; - 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 wrapUpDatabaseCalculation(bool calculationAborted){}; + unsigned int getNumberOfLayers() + { + return 0; + }; + unsigned int getNumberOfKnotsInLayer(unsigned int layerNum) + { + return 0; + }; + void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers) + { + }; + unsigned int getPartnerLayer(unsigned int layerNum) + { + return 0; + }; + string getOutputInformation(unsigned int layerNum) + { + return string(""); + }; + void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel) + { + }; + bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) + { + return false; + }; + bool getOpponentLevel(unsigned int threadNo) + { + return false; + }; + unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber) + { + return 0; + }; + unsigned int getLayerNumber(unsigned int threadNo) + { + return 0; + }; + 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 wrapUpDatabaseCalculation(bool calculationAborted) + { + }; public: - // Constructor / destructor - MiniMaxAI(); - ~MiniMaxAI(); + // Constructor / destructor + MiniMaxAI(); + ~MiniMaxAI(); - // Functions - void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); - void setSearchDepth(unsigned int depth); + // Functions + void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); + void setSearchDepth(unsigned int depth); }; #endif \ No newline at end of file diff --git a/src/perfect/miniMaxWin.h b/src/perfect/miniMaxWin.h index 155e0e1e..401232f8 100644 --- a/src/perfect/miniMaxWin.h +++ b/src/perfect/miniMaxWin.h @@ -1,9 +1,9 @@ /********************************************************************* - miniMaxWin.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMaxWin.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef MINIMAXWIN_H @@ -19,9 +19,15 @@ class MiniMaxGuiField { public: - virtual void setAlignment(wildWeasel::alignment &newAlignment){}; - virtual void setVisibility(bool visible){}; - virtual void setState(unsigned int curShowedLayer, MiniMax::StateNumberVarType curShowedState){}; + virtual void setAlignment(wildWeasel::alignment &newAlignment) + { + }; + virtual void setVisibility(bool visible) + { + }; + virtual void setState(unsigned int curShowedLayer, MiniMax::StateNumberVarType curShowedState) + { + }; }; /*------------------------------------------------------------------------------------ @@ -52,23 +58,23 @@ public: class MiniMaxWinInspectDb { protected: - // General Variables - MiniMax *pMiniMax = nullptr; // pointer to perfect AI class granting the access to the database - MiniMaxGuiField *pGuiField = nullptr; - bool showingInspectionControls = false; - unsigned int curShowedLayer = 0; // current showed layer - MiniMax::StateNumberVarType curShowedState = 0; // current showed state - const unsigned int scrollBarWidth = 20; + // General Variables + MiniMax *pMiniMax = nullptr; // pointer to perfect AI class granting the access to the database + MiniMaxGuiField *pGuiField = nullptr; + bool showingInspectionControls = false; + unsigned int curShowedLayer = 0; // current showed layer + MiniMax::StateNumberVarType curShowedState = 0; // current showed state + const unsigned int scrollBarWidth = 20; public: - // Constructor / destructor - MiniMaxWinInspectDb(wildWeasel::masterMind *ww, MiniMax *pMiniMax, wildWeasel::alignment &amInspectDb, wildWeasel::font2D *font, wildWeasel::texture *textureLine, MiniMaxGuiField &guiField); - ~MiniMaxWinInspectDb(); + // Constructor / destructor + MiniMaxWinInspectDb(wildWeasel::masterMind *ww, MiniMax *pMiniMax, wildWeasel::alignment &amInspectDb, wildWeasel::font2D *font, wildWeasel::texture *textureLine, MiniMaxGuiField &guiField); + ~MiniMaxWinInspectDb(); - // Generals Functions - bool createControls(); - bool showControls(bool visible); - void resize(wildWeasel::alignment &rcNewArea); + // Generals Functions + bool createControls(); + bool showControls(bool visible); + void resize(wildWeasel::alignment &rcNewArea); }; /*------------------------------------------------------------------------------------ @@ -102,59 +108,59 @@ public: class MiniMaxWinCalcDb { protected: - // Calculation variables - wildWeasel::masterMind *ww = nullptr; // pointer to engine - MiniMax *pMiniMax = nullptr; // pointer to perfect AI class granting the access to the database - ostream *outputStream = nullptr; // pointer to a stream for the console output of the calculation done by the class MiniMax - stringbuf outputStringBuf; // buffer linked to the stream, for reading out of the stream into the buffer - locale myLocale; // for formatting the output - queue layersToTest; // layer numbers to be tested - thread hThreadSolve; - thread hThreadTestLayer; - bool showingCalculationControls = false; - bool threadSolveIsRunning = false; - bool threadTestLayerIsRunning = false; - condition_variable threadConditionVariable; - mutex threadMutex; + // Calculation variables + wildWeasel::masterMind *ww = nullptr; // pointer to engine + MiniMax *pMiniMax = nullptr; // pointer to perfect AI class granting the access to the database + ostream *outputStream = nullptr; // pointer to a stream for the console output of the calculation done by the class MiniMax + stringbuf outputStringBuf; // buffer linked to the stream, for reading out of the stream into the buffer + locale myLocale; // for formatting the output + queue layersToTest; // layer numbers to be tested + thread hThreadSolve; + thread hThreadTestLayer; + bool showingCalculationControls = false; + bool threadSolveIsRunning = false; + bool threadTestLayerIsRunning = false; + condition_variable threadConditionVariable; + mutex threadMutex; - // positions, metrics, sizes, dimensions - unsigned int listViewRowHeight = 20; // height in pixel of a single row - const float defPixelDist = 15; // - const float labelHeight = 30; // - const float buttonHeight = 30; // + // positions, metrics, sizes, dimensions + unsigned int listViewRowHeight = 20; // height in pixel of a single row + const float defPixelDist = 15; // + const float labelHeight = 30; // + const float buttonHeight = 30; // - // Calculation Functions - void buttonFuncCalcStartOrContinue(void *pUser); - void buttonFuncCalcCancel(void *pUser); - void buttonFuncCalcPause(void *pUser); - void buttonFuncCalcTest(); - void buttonFuncCalcTestAll(void *pUser); - void buttonFuncCalcTestLayer(void *pUser); - void lvSelectedLayerChanged(unsigned int row, unsigned int col, wildWeasel::guiElemEvFol *guiElem, void *pUser); - static void updateOutputControls(void *pUser); - void updateListItemLayer(unsigned int layerNumber); - void updateListItemArray(MiniMax::ArrayInfoChange infoChange); - void threadSolve(); - void threadProcTestLayer(); + // Calculation Functions + void buttonFuncCalcStartOrContinue(void *pUser); + void buttonFuncCalcCancel(void *pUser); + void buttonFuncCalcPause(void *pUser); + void buttonFuncCalcTest(); + void buttonFuncCalcTestAll(void *pUser); + void buttonFuncCalcTestLayer(void *pUser); + void lvSelectedLayerChanged(unsigned int row, unsigned int col, wildWeasel::guiElemEvFol *guiElem, void *pUser); + static void updateOutputControls(void *pUser); + void updateListItemLayer(unsigned int layerNumber); + void updateListItemArray(MiniMax::ArrayInfoChange infoChange); + void threadSolve(); + void threadProcTestLayer(); public: - // Constructor / destructor - MiniMaxWinCalcDb(wildWeasel::masterMind *ww, MiniMax *pMiniMax, wildWeasel::alignment &amCalculation, wildWeasel::font2D *font, wildWeasel::texture *textureLine); - ~MiniMaxWinCalcDb(); + // Constructor / destructor + MiniMaxWinCalcDb(wildWeasel::masterMind *ww, MiniMax *pMiniMax, wildWeasel::alignment &amCalculation, wildWeasel::font2D *font, wildWeasel::texture *textureLine); + ~MiniMaxWinCalcDb(); - // Generals Functions - bool createControls(); - void resize(wildWeasel::alignment &amNewArea); - bool showControls(bool visible); - bool isCalculationOngoing(); - MiniMax *getMinimaxPointer() - { - return pMiniMax; - }; - CRITICAL_SECTION *getCriticalSectionOutput() - { - return &pMiniMax->csOsPrint; - }; + // Generals Functions + bool createControls(); + void resize(wildWeasel::alignment &amNewArea); + bool showControls(bool visible); + bool isCalculationOngoing(); + MiniMax *getMinimaxPointer() + { + return pMiniMax; + }; + CRITICAL_SECTION *getCriticalSectionOutput() + { + return &pMiniMax->csOsPrint; + }; }; #endif \ No newline at end of file diff --git a/src/perfect/miniMax_alphaBetaAlgorithmn.cpp b/src/perfect/miniMax_alphaBetaAlgorithmn.cpp index 1162a872..1ae40b20 100644 --- a/src/perfect/miniMax_alphaBetaAlgorithmn.cpp +++ b/src/perfect/miniMax_alphaBetaAlgorithmn.cpp @@ -1,9 +1,9 @@ /********************************************************************* - miniMax_alphaBetaAlgorithmn.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax_alphaBetaAlgorithmn.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMax.h" @@ -14,32 +14,30 @@ //----------------------------------------------------------------------------- bool MiniMax::calcKnotValuesByAlphaBeta(unsigned int layerNumber) { - // locals - AlphaBetaGlobalVars alphaBetaVars(this, layerNumber); // multi-thread vars + // locals + AlphaBetaGlobalVars alphaBetaVars(this, layerNumber); // multi-thread vars - // Version 10: - PRINT(1, this, "*** Calculate layer " << layerNumber << " by alpha-beta-algorithmn ***" << endl); - curCalculationActionId = MM_ACTION_PERFORM_ALPHA_BETA; + // Version 10: + PRINT(1, this, "*** Calculate layer " << layerNumber << " by alpha-beta-algorithmn ***" << endl); + curCalculationActionId = MM_ACTION_PERFORM_ALPHA_BETA; - // initialization - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - if (!initAlphaBeta(alphaBetaVars)) - { - return false; - } + // initialization + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + if (!initAlphaBeta(alphaBetaVars)) { + return false; + } - // run alpha-beta algorithmn - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - if (!runAlphaBeta(alphaBetaVars)) - { - return false; - } + // run alpha-beta algorithmn + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + if (!runAlphaBeta(alphaBetaVars)) { + return false; + } - // update layerStats[].numWonStates, etc. - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - showLayerStats(layerNumber); + // update layerStats[].numWonStates, etc. + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + showLayerStats(layerNumber); - return true; + return true; } //----------------------------------------------------------------------------- @@ -48,41 +46,40 @@ bool MiniMax::calcKnotValuesByAlphaBeta(unsigned int layerNumber) //----------------------------------------------------------------------------- void MiniMax::alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue, PlyInfoVarType plyValue, bool invertValue) { - // locals - unsigned int *symStateNumbers = nullptr; - unsigned int numSymmetricStates; - unsigned int sysStateNumber; - unsigned int i; + // locals + unsigned int *symStateNumbers = nullptr; + unsigned int numSymmetricStates; + unsigned int sysStateNumber; + unsigned int i; - // invert value ? - if (knotValue > SKV_VALUE_GAME_WON) - while (true) - ; - if (invertValue) - knotValue = skvPerspectiveMatrix[knotValue][PL_TO_MOVE_UNCHANGED]; + // invert value ? + if (knotValue > SKV_VALUE_GAME_WON) + while (true) + ; + if (invertValue) + knotValue = skvPerspectiveMatrix[knotValue][PL_TO_MOVE_UNCHANGED]; - // get numbers of symmetric states - getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers); + // get numbers of symmetric states + getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers); - // save - saveKnotValueInDatabase(layerNumber, stateNumber, knotValue); - savePlyInfoInDatabase(layerNumber, stateNumber, plyValue); + // save + saveKnotValueInDatabase(layerNumber, stateNumber, knotValue); + savePlyInfoInDatabase(layerNumber, stateNumber, plyValue); - // save value for all symmetric states - for (i = 0; i < numSymmetricStates; i++) - { + // save value for all symmetric states + for (i = 0; i < numSymmetricStates; i++) { - // get state number - sysStateNumber = symStateNumbers[i]; + // get state number + sysStateNumber = symStateNumbers[i]; - // don't save original state twice - if (sysStateNumber == stateNumber) - continue; + // don't save original state twice + if (sysStateNumber == stateNumber) + continue; - // save - saveKnotValueInDatabase(layerNumber, sysStateNumber, knotValue); - savePlyInfoInDatabase(layerNumber, sysStateNumber, plyValue); - } + // save + saveKnotValueInDatabase(layerNumber, sysStateNumber, knotValue); + savePlyInfoInDatabase(layerNumber, sysStateNumber, plyValue); + } } //----------------------------------------------------------------------------- @@ -91,74 +88,71 @@ void MiniMax::alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerN //----------------------------------------------------------------------------- bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars) { - // locals - BufferedFile *invalidArray; // - bool initAlreadyDone = false; // true if the initialization information is already available in a file - stringstream ssInvArrayDirectory; // - stringstream ssInvArrayFilePath; // + // locals + BufferedFile *invalidArray; // + bool initAlreadyDone = false; // true if the initialization information is already available in a file + stringstream ssInvArrayDirectory; // + stringstream ssInvArrayFilePath; // - // set current processed layer number - PRINT(1, this, endl << " *** Signing of invalid states for layer " << alphaBetaVars.layerNumber << " (" << (getOutputInformation(alphaBetaVars.layerNumber)) << ") which has " << layerStats[alphaBetaVars.layerNumber].knotsInLayer << " knots ***"); + // set current processed layer number + PRINT(1, this, endl << " *** Signing of invalid states for layer " << alphaBetaVars.layerNumber << " (" << (getOutputInformation(alphaBetaVars.layerNumber)) << ") which has " << layerStats[alphaBetaVars.layerNumber].knotsInLayer << " knots ***"); - // file names - ssInvArrayDirectory.str(""); - ssInvArrayDirectory << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates"; - ssInvArrayFilePath.str(""); - ssInvArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates\\invalidStatesOfLayer" << alphaBetaVars.layerNumber << ".dat"; + // file names + ssInvArrayDirectory.str(""); + ssInvArrayDirectory << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates"; + ssInvArrayFilePath.str(""); + ssInvArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates\\invalidStatesOfLayer" << alphaBetaVars.layerNumber << ".dat"; - // does initialization file exist ? - CreateDirectoryA(ssInvArrayDirectory.str().c_str(), nullptr); - invalidArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInvArrayFilePath.str().c_str()); - if (invalidArray->getFileSize() == (LONGLONG)layerStats[alphaBetaVars.layerNumber].knotsInLayer) - { - PRINT(2, this, " Loading invalid states from file: " << ssInvArrayFilePath.str()); - initAlreadyDone = true; - } + // does initialization file exist ? + CreateDirectoryA(ssInvArrayDirectory.str().c_str(), nullptr); + invalidArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInvArrayFilePath.str().c_str()); + if (invalidArray->getFileSize() == (LONGLONG)layerStats[alphaBetaVars.layerNumber].knotsInLayer) { + PRINT(2, this, " Loading invalid states from file: " << ssInvArrayFilePath.str()); + initAlreadyDone = true; + } - // prepare parameters - numStatesProcessed = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0; - ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), InitAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber, invalidArray, initAlreadyDone)); + // prepare parameters + numStatesProcessed = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0; + ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), InitAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber, invalidArray, initAlreadyDone)); - // 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)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - SAFE_DELETE(invalidArray); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - PRINT(0, this, "\n****************************************\nMain thread: Invalid or unexpected param!\n****************************************\n"); - return falseOrStop(); - } + // 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)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + SAFE_DELETE(invalidArray); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + PRINT(0, this, "\n****************************************\nMain thread: Invalid or unexpected param!\n****************************************\n"); + return falseOrStop(); + } - // reduce and delete thread specific data - tva.reduce(); - if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) - { - SAFE_DELETE(invalidArray); - return falseOrStop(); - } - invalidArray->flushBuffers(); - SAFE_DELETE(invalidArray); + // reduce and delete thread specific data + tva.reduce(); + if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) { + SAFE_DELETE(invalidArray); + return falseOrStop(); + } + invalidArray->flushBuffers(); + SAFE_DELETE(invalidArray); - // when init file was created new then save it now - PRINT(2, this, " Saved initialized states to file: " << ssInvArrayFilePath.str()); + // when init file was created new then save it now + PRINT(2, this, " Saved initialized states to file: " << ssInvArrayFilePath.str()); - // show statistics - PRINT(2, this, " won states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON]); - PRINT(2, this, " lost states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST]); - PRINT(2, this, " draw states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); - PRINT(2, this, " invalid states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID]); + // show statistics + PRINT(2, this, " won states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON]); + PRINT(2, this, " lost states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST]); + PRINT(2, this, " draw states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); + PRINT(2, this, " invalid states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID]); - return true; + return true; } //----------------------------------------------------------------------------- @@ -167,79 +161,64 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars) //----------------------------------------------------------------------------- DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index) { - // locals - InitAlphaBetaVars *iabVars = (InitAlphaBetaVars *)pParameter; - MiniMax *m = iabVars->pMiniMax; - float floatValue; // dummy variable for calls of getValueOfSituation() - StateAdress curState; // current state counter for loops - TwoBit curStateValue = 0; // for calls of getValueOfSituation() - PlyInfoVarType plyInfo; // depends on the curStateValue + // locals + InitAlphaBetaVars *iabVars = (InitAlphaBetaVars *)pParameter; + MiniMax *m = iabVars->pMiniMax; + float floatValue; // dummy variable for calls of getValueOfSituation() + StateAdress curState; // current state counter for loops + TwoBit curStateValue = 0; // for calls of getValueOfSituation() + PlyInfoVarType plyInfo; // depends on the curStateValue - curState.layerNumber = iabVars->layerNumber; - curState.stateNumber = index; - iabVars->statesProcessed++; + curState.layerNumber = iabVars->layerNumber; + curState.stateNumber = index; + iabVars->statesProcessed++; - // print status - if (iabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); - } + // print status + if (iabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_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 - if (iabVars->initAlreadyDone) - { - if (!iabVars->bufferedFile->readBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) - { - PRINT(0, m, "ERROR: initArray->takeBytes() failed"); - return m->falseOrStop(); - } - // initialization not done - } - else - { - // set current selected situation - if (!m->setSituation(iabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) - { - curStateValue = SKV_VALUE_INVALID; - } - else - { - // get value of current situation - m->getValueOfSituation(iabVars->curThreadNo, floatValue, curStateValue); - } - } + // layer initialization already done ? if so, then read from file + if (iabVars->initAlreadyDone) { + if (!iabVars->bufferedFile->readBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) { + PRINT(0, m, "ERROR: initArray->takeBytes() failed"); + return m->falseOrStop(); + } + // initialization not done + } else { + // set current selected situation + if (!m->setSituation(iabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) { + curStateValue = SKV_VALUE_INVALID; + } else { + // get value of current situation + m->getValueOfSituation(iabVars->curThreadNo, floatValue, curStateValue); + } + } - // calc ply info - if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) - { - plyInfo = 0; - } - else if (curStateValue == SKV_VALUE_INVALID) - { - plyInfo = PLYINFO_VALUE_INVALID; - } - else - { - plyInfo = PLYINFO_VALUE_UNCALCULATED; - } + // calc ply info + if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) { + plyInfo = 0; + } else if (curStateValue == SKV_VALUE_INVALID) { + plyInfo = PLYINFO_VALUE_INVALID; + } else { + plyInfo = PLYINFO_VALUE_UNCALCULATED; + } - // save short knot value & ply info (m->alphaBetaSaveInDatabase(iabVars->curThreadNo, curStateValue, plyInfo, false); ???) - m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, plyInfo); + // save short knot value & ply info (m->alphaBetaSaveInDatabase(iabVars->curThreadNo, curStateValue, plyInfo, false); ???) + m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, plyInfo); - // write data to file - if (!iabVars->initAlreadyDone) - { - if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) - { - PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); - return m->falseOrStop(); - } - } - iabVars->statsValueCounter[curStateValue]++; + // write data to file + if (!iabVars->initAlreadyDone) { + if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) { + PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); + return m->falseOrStop(); + } + } + iabVars->statsValueCounter[curStateValue]++; - return TM_RETURN_VALUE_OK; + return TM_RETURN_VALUE_OK; } //----------------------------------------------------------------------------- @@ -248,45 +227,44 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index) //----------------------------------------------------------------------------- bool MiniMax::runAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars) { - // prepare parameters - PRINT(1, this, " Calculate layer " << alphaBetaVars.layerNumber << " with function letTheTreeGrow():"); - numStatesProcessed = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; - alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0; - ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), RunAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber)); + // prepare parameters + PRINT(1, this, " Calculate layer " << alphaBetaVars.layerNumber << " with function letTheTreeGrow():"); + numStatesProcessed = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; + alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0; + ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), RunAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber)); - // so far no multi-threadin implemented - threadManager.setNumThreads(1); + // so far no multi-threadin implemented + threadManager.setNumThreads(1); - // 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)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } - threadManager.setNumThreads(4); + // 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)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } + threadManager.setNumThreads(4); - // reduce and delete thread specific data - tva.reduce(); - if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) - return falseOrStop(); + // reduce and delete thread specific data + tva.reduce(); + if (numStatesProcessed < layerStats[alphaBetaVars.layerNumber].knotsInLayer) + return falseOrStop(); - // show statistics - PRINT(2, this, " won states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON]); - PRINT(2, this, " lost states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST]); - PRINT(2, this, " draw states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); - PRINT(2, this, " invalid states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID]); + // show statistics + PRINT(2, this, " won states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_WON]); + PRINT(2, this, " lost states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST]); + PRINT(2, this, " draw states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); + PRINT(2, this, " invalid states: " << alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID]); - return true; + return true; } //----------------------------------------------------------------------------- @@ -295,42 +273,38 @@ bool MiniMax::runAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars) //----------------------------------------------------------------------------- DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index) { - // locals - RunAlphaBetaVars *rabVars = (RunAlphaBetaVars *)pParameter; - MiniMax *m = rabVars->pMiniMax; - StateAdress curState; // current state counter for loops - Node root; // - PlyInfoVarType plyInfo; // depends on the curStateValue + // locals + RunAlphaBetaVars *rabVars = (RunAlphaBetaVars *)pParameter; + MiniMax *m = rabVars->pMiniMax; + StateAdress curState; // current state counter for loops + Node root; // + PlyInfoVarType plyInfo; // depends on the curStateValue - curState.layerNumber = rabVars->layerNumber; - curState.stateNumber = index; - rabVars->statesProcessed++; + curState.layerNumber = rabVars->layerNumber; + curState.stateNumber = index; + rabVars->statesProcessed++; - // print status - if (rabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(2, m, " Processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); - } + // print status + if (rabVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_STATES; + PRINT(2, m, " Processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); + } - // Version 10: state already calculated? if so leave. - m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, plyInfo); - if (plyInfo != PLYINFO_VALUE_UNCALCULATED) - return TM_RETURN_VALUE_OK; + // Version 10: state already calculated? if so leave. + m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, plyInfo); + if (plyInfo != PLYINFO_VALUE_UNCALCULATED) + return TM_RETURN_VALUE_OK; - // set current selected situation - if (m->setSituation(rabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) - { + // set current selected situation + if (m->setSituation(rabVars->curThreadNo, curState.layerNumber, curState.stateNumber)) { - // calc value of situation - m->letTheTreeGrow(&root, rabVars, m->depthOfFullTree, SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON); - } - else - { - // 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); - } - return TM_RETURN_VALUE_OK; + // calc value of situation + m->letTheTreeGrow(&root, rabVars, m->depthOfFullTree, SKV_VALUE_GAME_LOST, SKV_VALUE_GAME_WON); + } else { + // 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); + } + return TM_RETURN_VALUE_OK; } //----------------------------------------------------------------------------- @@ -339,91 +313,81 @@ DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index) //----------------------------------------------------------------------------- void MiniMax::letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, float alpha, float beta) { - // Locals - void *pPossibilities; - unsigned int *idPossibility; - unsigned int layerNumber = 0; // layer number of current state - unsigned int stateNumber = 0; // state number of current state - unsigned int maxWonfreqValuesSubMoves = 0; + // Locals + void *pPossibilities; + unsigned int *idPossibility; + unsigned int layerNumber = 0; // layer number of current state + unsigned int stateNumber = 0; // state number of current state + unsigned int maxWonfreqValuesSubMoves = 0; - // standard values - knot->branches = &rabVars->branchArray[(depthOfFullTree - tilLevel) * maxNumBranches]; - knot->numPossibilities = 0; - knot->bestBranch = 0; - knot->bestMoveId = 0; - knot->isOpponentLevel = getOpponentLevel(rabVars->curThreadNo); - knot->plyInfo = PLYINFO_VALUE_UNCALCULATED; - knot->shortValue = SKV_VALUE_GAME_DRAWN; - knot->floatValue = (float)knot->shortValue; + // standard values + knot->branches = &rabVars->branchArray[(depthOfFullTree - tilLevel) * maxNumBranches]; + knot->numPossibilities = 0; + knot->bestBranch = 0; + knot->bestMoveId = 0; + knot->isOpponentLevel = getOpponentLevel(rabVars->curThreadNo); + knot->plyInfo = PLYINFO_VALUE_UNCALCULATED; + knot->shortValue = SKV_VALUE_GAME_DRAWN; + knot->floatValue = (float)knot->shortValue; - // evaluate situation, musn't occur while calculating database - if (tilLevel == 0) - { - if (calcDatabase) - { - // if tilLevel is equal zero it means that memory is gone out, since each recursive step needs memory - PRINT(0, this, "ERROR: tilLevel == 0"); - knot->shortValue = SKV_VALUE_INVALID; - knot->plyInfo = PLYINFO_VALUE_INVALID; - knot->floatValue = (float)knot->shortValue; - falseOrStop(); - } - else - { - getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue); - } - // investigate branches - } - else - { + // evaluate situation, musn't occur while calculating database + if (tilLevel == 0) { + if (calcDatabase) { + // if tilLevel is equal zero it means that memory is gone out, since each recursive step needs memory + PRINT(0, this, "ERROR: tilLevel == 0"); + knot->shortValue = SKV_VALUE_INVALID; + knot->plyInfo = PLYINFO_VALUE_INVALID; + knot->floatValue = (float)knot->shortValue; + falseOrStop(); + } else { + getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue); + } + // investigate branches + } else { - // 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)) - return; + // 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)) + return; - // get number of possiblities - idPossibility = getPossibilities(rabVars->curThreadNo, &knot->numPossibilities, &knot->isOpponentLevel, &pPossibilities); + // get number of possiblities + idPossibility = getPossibilities(rabVars->curThreadNo, &knot->numPossibilities, &knot->isOpponentLevel, &pPossibilities); - // unable to move - if (knot->numPossibilities == 0) - { + // unable to move + if (knot->numPossibilities == 0) { - // if unable to move a final state is reached - knot->plyInfo = 0; - getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue); - if (tilLevel == depthOfFullTree - 1) - rabVars->freqValuesSubMoves[knot->shortValue]++; + // if unable to move a final state is reached + knot->plyInfo = 0; + getValueOfSituation(rabVars->curThreadNo, knot->floatValue, knot->shortValue); + if (tilLevel == depthOfFullTree - 1) + rabVars->freqValuesSubMoves[knot->shortValue]++; - // if unable to move an invalid state was reached if nobody has won - if (calcDatabase && knot->shortValue == SKV_VALUE_GAME_DRAWN) - { - knot->shortValue = SKV_VALUE_INVALID; - knot->plyInfo = PLYINFO_VALUE_INVALID; - knot->floatValue = (float)knot->shortValue; - } + // if unable to move an invalid state was reached if nobody has won + if (calcDatabase && knot->shortValue == SKV_VALUE_GAME_DRAWN) { + knot->shortValue = SKV_VALUE_INVALID; + knot->plyInfo = PLYINFO_VALUE_INVALID; + knot->floatValue = (float)knot->shortValue; + } - // movement is possible - } - else - { + // movement is possible + } else { - // move, letTreeGroe, undo - alphaBetaTryPossibilites(knot, rabVars, tilLevel, idPossibility, pPossibilities, maxWonfreqValuesSubMoves, alpha, beta); + // move, letTreeGroe, undo + alphaBetaTryPossibilites(knot, rabVars, tilLevel, idPossibility, pPossibilities, maxWonfreqValuesSubMoves, alpha, beta); - // calculate value of knot - its the value of the best branch - alphaBetaCalcKnotValue(knot); + // calculate value of knot - its the value of the best branch + alphaBetaCalcKnotValue(knot); - // calc ply info - alphaBetaCalcPlyInfo(knot); + // calc ply info + alphaBetaCalcPlyInfo(knot); - // select randomly one of the best moves, if they are equivalent - alphaBetaChooseBestMove(knot, rabVars, tilLevel, idPossibility, maxWonfreqValuesSubMoves); - } + // select randomly one of the best moves, if they are equivalent + alphaBetaChooseBestMove(knot, rabVars, tilLevel, idPossibility, maxWonfreqValuesSubMoves); + } - // save value and best branch into database and set value as valid - if (calcDatabase && hFileShortKnotValues && hFilePlyInfo) - alphaBetaSaveInDatabase(rabVars->curThreadNo, layerNumber, stateNumber, knot->shortValue, knot->plyInfo, knot->isOpponentLevel); - } + // save value and best branch into database and set value as valid + if (calcDatabase && hFileShortKnotValues && hFilePlyInfo) + alphaBetaSaveInDatabase(rabVars->curThreadNo, layerNumber, stateNumber, knot->shortValue, knot->plyInfo, knot->isOpponentLevel); + } } //----------------------------------------------------------------------------- @@ -435,51 +399,47 @@ void MiniMax::letTheTreeGrow(Node *knot, RunAlphaBetaVars *rabVars, unsigned int //----------------------------------------------------------------------------- bool MiniMax::alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int &layerNumber, unsigned int &stateNumber) { - // locals - bool invalidLayerOrStateNumber; - bool subLayerInDatabaseAndCompleted; - TwoBit shortKnotValue = SKV_VALUE_INVALID; - PlyInfoVarType plyInfo = PLYINFO_VALUE_UNCALCULATED; + // locals + bool invalidLayerOrStateNumber; + bool subLayerInDatabaseAndCompleted; + TwoBit shortKnotValue = SKV_VALUE_INVALID; + PlyInfoVarType plyInfo = PLYINFO_VALUE_UNCALCULATED; - // use database ? - if (hFilePlyInfo != nullptr && hFileShortKnotValues != nullptr && (calcDatabase || layerInDatabase)) - { + // use database ? + if (hFilePlyInfo != nullptr && hFileShortKnotValues != nullptr && (calcDatabase || layerInDatabase)) { - // situation already existend in database ? - readKnotValueFromDatabase(rabVars->curThreadNo, layerNumber, stateNumber, shortKnotValue, invalidLayerOrStateNumber, subLayerInDatabaseAndCompleted); - readPlyInfoFromDatabase(layerNumber, stateNumber, plyInfo); + // situation already existend in database ? + readKnotValueFromDatabase(rabVars->curThreadNo, layerNumber, stateNumber, shortKnotValue, invalidLayerOrStateNumber, subLayerInDatabaseAndCompleted); + readPlyInfoFromDatabase(layerNumber, stateNumber, plyInfo); - // it was possible to achieve an invalid state using move(), - // 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)) - { // version 22: replaced: curCalculatedLayer == layerNumber && knot->plyInfo != PLYINFO_VALUE_UNCALCULATED)) { - knot->shortValue = SKV_VALUE_INVALID; - knot->plyInfo = PLYINFO_VALUE_INVALID; - knot->floatValue = (float)knot->shortValue; - return true; - } + // it was possible to achieve an invalid state using move(), + // 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)) { // version 22: replaced: curCalculatedLayer == layerNumber && knot->plyInfo != PLYINFO_VALUE_UNCALCULATED)) { + knot->shortValue = SKV_VALUE_INVALID; + knot->plyInfo = PLYINFO_VALUE_INVALID; + knot->floatValue = (float)knot->shortValue; + return true; + } - // print out put, if not calculating database, but requesting a knot value - 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 out put, if not calculating database, but requesting a knot value + 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); + } - // 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) - { + // 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) { - // switch if is not opponent level - if (knot->isOpponentLevel) - knot->shortValue = skvPerspectiveMatrix[shortKnotValue][PL_TO_MOVE_UNCHANGED]; - else - knot->shortValue = skvPerspectiveMatrix[shortKnotValue][PL_TO_MOVE_CHANGED]; - knot->floatValue = (float)knot->shortValue; - knot->plyInfo = plyInfo; - return true; - } - } - return false; + // switch if is not opponent level + if (knot->isOpponentLevel) + knot->shortValue = skvPerspectiveMatrix[shortKnotValue][PL_TO_MOVE_UNCHANGED]; + else + knot->shortValue = skvPerspectiveMatrix[shortKnotValue][PL_TO_MOVE_CHANGED]; + knot->floatValue = (float)knot->shortValue; + knot->plyInfo = plyInfo; + return true; + } + } + return false; } //----------------------------------------------------------------------------- @@ -488,97 +448,76 @@ bool MiniMax::alphaBetaTryDataBase(Node *knot, RunAlphaBetaVars *rabVars, unsign //----------------------------------------------------------------------------- void MiniMax::alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, void *pPossibilities, unsigned int &maxWonfreqValuesSubMoves, float &alpha, float &beta) { - // locals - void *pBackup; - unsigned int curPoss; + // locals + void *pBackup; + unsigned int curPoss; - for (curPoss = 0; curPoss < knot->numPossibilities; curPoss++) - { + for (curPoss = 0; curPoss < knot->numPossibilities; curPoss++) { - // output - if (tilLevel == depthOfFullTree && !calcDatabase) - { - printMoveInformation(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities); - rabVars->freqValuesSubMoves[SKV_VALUE_INVALID] = 0; - rabVars->freqValuesSubMoves[SKV_VALUE_GAME_LOST] = 0; - rabVars->freqValuesSubMoves[SKV_VALUE_GAME_DRAWN] = 0; - rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON] = 0; - } + // output + if (tilLevel == depthOfFullTree && !calcDatabase) { + printMoveInformation(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities); + rabVars->freqValuesSubMoves[SKV_VALUE_INVALID] = 0; + rabVars->freqValuesSubMoves[SKV_VALUE_GAME_LOST] = 0; + rabVars->freqValuesSubMoves[SKV_VALUE_GAME_DRAWN] = 0; + rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON] = 0; + } - // move - move(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, &pBackup, pPossibilities); + // move + move(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, &pBackup, pPossibilities); - // recursive call - letTheTreeGrow(&knot->branches[curPoss], rabVars, tilLevel - 1, alpha, beta); + // recursive call + letTheTreeGrow(&knot->branches[curPoss], rabVars, tilLevel - 1, alpha, beta); - // undo move - undo(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, pBackup, pPossibilities); + // undo move + undo(rabVars->curThreadNo, idPossibility[curPoss], knot->isOpponentLevel, pBackup, pPossibilities); - // output - if (tilLevel == depthOfFullTree && !calcDatabase) - { - 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) - { - maxWonfreqValuesSubMoves = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON]; - } - if (hFileShortKnotValues != nullptr && layerInDatabase) - { - 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); - } - else - { - PRINT(0, this, "\t: " << knot->branches[curPoss].floatValue << endl); - } - } - else if (tilLevel == depthOfFullTree - 1 && !calcDatabase) - { - rabVars->freqValuesSubMoves[knot->branches[curPoss].shortValue]++; - } + // output + if (tilLevel == depthOfFullTree && !calcDatabase) { + 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) { + maxWonfreqValuesSubMoves = rabVars->freqValuesSubMoves[SKV_VALUE_GAME_WON]; + } + if (hFileShortKnotValues != nullptr && layerInDatabase) { + 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); + } else { + PRINT(0, this, "\t: " << knot->branches[curPoss].floatValue << endl); + } + } else if (tilLevel == depthOfFullTree - 1 && !calcDatabase) { + rabVars->freqValuesSubMoves[knot->branches[curPoss].shortValue]++; + } - // don't use alpha beta if using database - if (hFileShortKnotValues != nullptr && calcDatabase) - continue; - if (hFileShortKnotValues != nullptr && tilLevel + 1 >= depthOfFullTree) - continue; + // don't use alpha beta if using database + if (hFileShortKnotValues != nullptr && calcDatabase) + continue; + if (hFileShortKnotValues != nullptr && tilLevel + 1 >= depthOfFullTree) + continue; - // alpha beta algorithmn - if (!knot->isOpponentLevel) - { - if (knot->branches[curPoss].floatValue >= beta) - { - knot->numPossibilities = curPoss + 1; - break; - } - else if (knot->branches[curPoss].floatValue > alpha) - { - alpha = knot->branches[curPoss].floatValue; - } - } - else - { - if (knot->branches[curPoss].floatValue <= alpha) - { - knot->numPossibilities = curPoss + 1; - break; - } - else if (knot->branches[curPoss].floatValue < beta) - { - beta = knot->branches[curPoss].floatValue; - } - } - } + // alpha beta algorithmn + if (!knot->isOpponentLevel) { + if (knot->branches[curPoss].floatValue >= beta) { + knot->numPossibilities = curPoss + 1; + break; + } else if (knot->branches[curPoss].floatValue > alpha) { + alpha = knot->branches[curPoss].floatValue; + } + } else { + if (knot->branches[curPoss].floatValue <= alpha) { + knot->numPossibilities = curPoss + 1; + break; + } else if (knot->branches[curPoss].floatValue < beta) { + beta = knot->branches[curPoss].floatValue; + } + } + } - // let delete pPossibilities - if (tilLevel < depthOfFullTree) - { - deletePossibilities(rabVars->curThreadNo, pPossibilities); - } - else - { - pRootPossibilities = pPossibilities; - } + // let delete pPossibilities + if (tilLevel < depthOfFullTree) { + deletePossibilities(rabVars->curThreadNo, pPossibilities); + } else { + pRootPossibilities = pPossibilities; + } } //----------------------------------------------------------------------------- @@ -587,40 +526,33 @@ void MiniMax::alphaBetaTryPossibilites(Node *knot, RunAlphaBetaVars *rabVars, un //----------------------------------------------------------------------------- void MiniMax::alphaBetaCalcKnotValue(Node *knot) { - // locals - float maxValue = knot->branches[0].floatValue; - unsigned int maxBranch = 0; - unsigned int i; + // locals + float maxValue = knot->branches[0].floatValue; + unsigned int maxBranch = 0; + unsigned int i; - // opponent tries to minimize the value - if (knot->isOpponentLevel) - { - for (i = 1; i < knot->numPossibilities; i++) - { - // 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) - { - maxValue = knot->branches[i].floatValue; - maxBranch = i; - } - } - // maximize the value - } - else - { - for (i = 1; i < knot->numPossibilities; i++) - { - if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue > maxValue) - { - maxValue = knot->branches[i].floatValue; - maxBranch = i; - } - } - } + // opponent tries to minimize the value + if (knot->isOpponentLevel) { + for (i = 1; i < knot->numPossibilities; i++) { + // 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) { + maxValue = knot->branches[i].floatValue; + maxBranch = i; + } + } + // maximize the value + } else { + for (i = 1; i < knot->numPossibilities; i++) { + if (/*knot->shortValue != SKV_VALUE_INVALID && */ knot->branches[i].floatValue > maxValue) { + maxValue = knot->branches[i].floatValue; + maxBranch = i; + } + } + } - // set value - knot->floatValue = knot->branches[maxBranch].floatValue; - knot->shortValue = knot->branches[maxBranch].shortValue; + // set value + knot->floatValue = knot->branches[maxBranch].floatValue; + knot->shortValue = knot->branches[maxBranch].shortValue; } //----------------------------------------------------------------------------- @@ -629,78 +561,66 @@ void MiniMax::alphaBetaCalcKnotValue(Node *knot) //----------------------------------------------------------------------------- void MiniMax::alphaBetaCalcPlyInfo(Node *knot) { - // locals - unsigned int i; - unsigned int maxBranch; - PlyInfoVarType maxPlyInfo; - TwoBit shortKnotValue; + // locals + unsigned int i; + unsigned int maxBranch; + PlyInfoVarType maxPlyInfo; + TwoBit shortKnotValue; - // - if (knot->shortValue == SKV_VALUE_GAME_DRAWN) - { - knot->plyInfo = PLYINFO_VALUE_DRAWN; - } - else if (knot->shortValue == SKV_VALUE_INVALID) - { - knot->plyInfo = PLYINFO_VALUE_INVALID; - } - else - { + // + if (knot->shortValue == SKV_VALUE_GAME_DRAWN) { + knot->plyInfo = PLYINFO_VALUE_DRAWN; + } else if (knot->shortValue == SKV_VALUE_INVALID) { + knot->plyInfo = PLYINFO_VALUE_INVALID; + } else { - // calculate value of knot - shortKnotValue = (knot->isOpponentLevel) ? skvPerspectiveMatrix[knot->shortValue][PL_TO_MOVE_UNCHANGED] : knot->shortValue; - maxPlyInfo = (shortKnotValue == SKV_VALUE_GAME_WON) ? PLYINFO_VALUE_DRAWN : 0; - maxBranch = 0; + // calculate value of knot + shortKnotValue = (knot->isOpponentLevel) ? skvPerspectiveMatrix[knot->shortValue][PL_TO_MOVE_UNCHANGED] : knot->shortValue; + maxPlyInfo = (shortKnotValue == SKV_VALUE_GAME_WON) ? PLYINFO_VALUE_DRAWN : 0; + maxBranch = 0; - // when current knot is a won state - if (shortKnotValue == SKV_VALUE_GAME_WON) - { + // when current knot is a won state + 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 - shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; + // invert knot value if necessary + shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; - // take the minimum of the lost states (negative float values) - if ((knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel != knot->branches[i].isOpponentLevel) + // take the minimum of the lost states (negative float values) + 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 - || (knot->branches[i].plyInfo < maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) - { + // 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)) { - maxPlyInfo = knot->branches[i].plyInfo; - maxBranch = i; - } - } + maxPlyInfo = knot->branches[i].plyInfo; + maxBranch = i; + } + } - // current state is a lost state - } - else - { + // current state is a lost state + } else { - for (i = 0; i < knot->numPossibilities; i++) - { + for (i = 0; i < knot->numPossibilities; i++) { - // invert knot value if necessary - shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; + // invert knot value if necessary + shortKnotValue = (knot->branches[i].isOpponentLevel) ? skvPerspectiveMatrix[knot->branches[i].shortValue][PL_TO_MOVE_UNCHANGED] : knot->branches[i].shortValue; - // after this move the same player will continue, so take the maximum of the lost states (negative float values) - if ((knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_WON && knot->isOpponentLevel != knot->branches[i].isOpponentLevel) + // after this move the same player will continue, so take the maximum of the lost states (negative float values) + 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 - || (knot->branches[i].plyInfo > maxPlyInfo && shortKnotValue == SKV_VALUE_GAME_LOST && knot->isOpponentLevel == knot->branches[i].isOpponentLevel)) - { + // 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)) { - maxPlyInfo = knot->branches[i].plyInfo; - maxBranch = i; - } - } - } + maxPlyInfo = knot->branches[i].plyInfo; + maxBranch = i; + } + } + } - // set value - knot->plyInfo = knot->branches[maxBranch].plyInfo + 1; - } + // set value + knot->plyInfo = knot->branches[maxBranch].plyInfo + 1; + } } //----------------------------------------------------------------------------- @@ -709,67 +629,55 @@ void MiniMax::alphaBetaCalcPlyInfo(Node *knot) //----------------------------------------------------------------------------- void MiniMax::alphaBetaChooseBestMove(Node *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, unsigned int maxWonfreqValuesSubMoves) { - // locals - float dif; - unsigned int numBestChoices = 0; - unsigned int *bestBranches = new unsigned int[maxNumBranches]; - unsigned int i; - unsigned int maxBranch; + // locals + float dif; + unsigned int numBestChoices = 0; + unsigned int *bestBranches = new unsigned int[maxNumBranches]; + unsigned int i; + unsigned int maxBranch; - // select randomly one of the best moves, if they are equivalent - if (tilLevel == depthOfFullTree && !calcDatabase) - { + // select randomly one of the best moves, if they are equivalent + if (tilLevel == depthOfFullTree && !calcDatabase) { - // check every possible move - for (numBestChoices = 0, i = 0; i < knot->numPossibilities; i++) - { + // check every possible move + for (numBestChoices = 0, i = 0; i < knot->numPossibilities; i++) { - // use information in database - if (layerInDatabase && hFileShortKnotValues != nullptr) - { + // use information in database + if (layerInDatabase && hFileShortKnotValues != nullptr) { - // selected move with equal knot value - if (knot->branches[i].shortValue == knot->shortValue) - { + // selected move with equal knot value + if (knot->branches[i].shortValue == knot->shortValue) { - // best move lead to drawn state - if (knot->shortValue == SKV_VALUE_GAME_DRAWN) - { - if (maxWonfreqValuesSubMoves == rabVars->freqValuesSubMovesBranchWon[i]) - { - bestBranches[numBestChoices] = i; - numBestChoices++; - } + // best move lead to drawn state + if (knot->shortValue == SKV_VALUE_GAME_DRAWN) { + if (maxWonfreqValuesSubMoves == rabVars->freqValuesSubMovesBranchWon[i]) { + bestBranches[numBestChoices] = i; + numBestChoices++; + } - // best move lead to lost or won state - } - else - { - if (knot->plyInfo == knot->branches[i].plyInfo + 1) - { - bestBranches[numBestChoices] = i; - numBestChoices++; - } - } - } - // conventionell mini-max algorithm - } - else - { - dif = knot->branches[i].floatValue - knot->floatValue; - dif = (dif > 0) ? dif : -1.0f * dif; - if (dif < FPKV_THRESHOLD) - { - bestBranches[numBestChoices] = i; - numBestChoices++; - } - } - } - } + // best move lead to lost or won state + } else { + if (knot->plyInfo == knot->branches[i].plyInfo + 1) { + bestBranches[numBestChoices] = i; + numBestChoices++; + } + } + } + // conventionell mini-max algorithm + } else { + dif = knot->branches[i].floatValue - knot->floatValue; + dif = (dif > 0) ? dif : -1.0f * dif; + if (dif < FPKV_THRESHOLD) { + bestBranches[numBestChoices] = i; + numBestChoices++; + } + } + } + } - // set value - maxBranch = (numBestChoices ? bestBranches[rand() % numBestChoices] : 0); - knot->bestMoveId = idPossibility[maxBranch]; - knot->bestBranch = maxBranch; - SAFE_DELETE_ARRAY(bestBranches); + // set value + maxBranch = (numBestChoices ? bestBranches[rand() % numBestChoices] : 0); + knot->bestMoveId = idPossibility[maxBranch]; + knot->bestBranch = maxBranch; + SAFE_DELETE_ARRAY(bestBranches); } diff --git a/src/perfect/miniMax_database.cpp b/src/perfect/miniMax_database.cpp index e8f60b1d..256705eb 100644 --- a/src/perfect/miniMax_database.cpp +++ b/src/perfect/miniMax_database.cpp @@ -1,9 +1,9 @@ /********************************************************************* - miniMax_database.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax_database.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMax.h" @@ -14,23 +14,21 @@ //----------------------------------------------------------------------------- void MiniMax::closeDatabase() { - // close database - if (hFileShortKnotValues != nullptr) - { - unloadAllLayers(); - SAFE_DELETE_ARRAY(layerStats); - CloseHandle(hFileShortKnotValues); - hFileShortKnotValues = nullptr; - } + // close database + if (hFileShortKnotValues != nullptr) { + unloadAllLayers(); + SAFE_DELETE_ARRAY(layerStats); + CloseHandle(hFileShortKnotValues); + hFileShortKnotValues = nullptr; + } - // close ply information file - if (hFilePlyInfo != nullptr) - { - unloadAllPlyInfos(); - SAFE_DELETE_ARRAY(plyInfos); - CloseHandle(hFilePlyInfo); - hFilePlyInfo = nullptr; - } + // close ply information file + if (hFilePlyInfo != nullptr) { + unloadAllPlyInfos(); + SAFE_DELETE_ARRAY(plyInfos); + CloseHandle(hFilePlyInfo); + hFilePlyInfo = nullptr; + } } //----------------------------------------------------------------------------- @@ -39,11 +37,11 @@ void MiniMax::closeDatabase() //----------------------------------------------------------------------------- void MiniMax::unloadPlyInfo(unsigned int layerNumber) { - PlyInfo *myPis = &plyInfos[layerNumber]; - memoryUsed2 -= myPis->sizeInBytes; - arrayInfos.removeArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); - SAFE_DELETE_ARRAY(myPis->plyInfo); - myPis->plyInfoIsLoaded = false; + PlyInfo *myPis = &plyInfos[layerNumber]; + memoryUsed2 -= myPis->sizeInBytes; + arrayInfos.removeArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); + SAFE_DELETE_ARRAY(myPis->plyInfo); + myPis->plyInfoIsLoaded = false; } //----------------------------------------------------------------------------- @@ -52,11 +50,11 @@ void MiniMax::unloadPlyInfo(unsigned int layerNumber) //----------------------------------------------------------------------------- void MiniMax::unloadLayer(unsigned int layerNumber) { - LayerStats *myLss = &layerStats[layerNumber]; - SAFE_DELETE_ARRAY(myLss->shortKnotValueByte); - memoryUsed2 -= myLss->sizeInBytes; - arrayInfos.removeArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); - myLss->layerIsLoaded = false; + LayerStats *myLss = &layerStats[layerNumber]; + SAFE_DELETE_ARRAY(myLss->shortKnotValueByte); + memoryUsed2 -= myLss->sizeInBytes; + arrayInfos.removeArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); + myLss->layerIsLoaded = false; } //----------------------------------------------------------------------------- @@ -65,10 +63,9 @@ void MiniMax::unloadLayer(unsigned int layerNumber) //----------------------------------------------------------------------------- void MiniMax::unloadAllPlyInfos() { - for (unsigned int i = 0; i < plyInfoHeader.numLayers; i++) - { - unloadPlyInfo(i); - } + for (unsigned int i = 0; i < plyInfoHeader.numLayers; i++) { + unloadPlyInfo(i); + } } //----------------------------------------------------------------------------- @@ -77,10 +74,9 @@ void MiniMax::unloadAllPlyInfos() //----------------------------------------------------------------------------- void MiniMax::unloadAllLayers() { - for (unsigned int i = 0; i < skvfHeader.numLayers; i++) - { - unloadLayer(i); - } + for (unsigned int i = 0; i < skvfHeader.numLayers; i++) { + unloadLayer(i); + } } //----------------------------------------------------------------------------- @@ -89,36 +85,31 @@ void MiniMax::unloadAllLayers() //----------------------------------------------------------------------------- void MiniMax::saveBytesToFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes) { - DWORD dwBytesWritten; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = numBytes; - void *myPointer = pBytes; - bool errorPrint = false; + DWORD dwBytesWritten; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = numBytes; + void *myPointer = pBytes; + bool errorPrint = false; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - { - if (!errorPrint) - PRINT(1, this, "ERROR: SetFilePointerEx failed!"); - } + while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) { + if (!errorPrint) + PRINT(1, this, "ERROR: SetFilePointerEx failed!"); + } - while (restingBytes > 0) - { - if (WriteFile(hFile, myPointer, restingBytes, &dwBytesWritten, nullptr) == TRUE) - { - restingBytes -= dwBytesWritten; - myPointer = (void *)(((unsigned char *)myPointer) + dwBytesWritten); - if (restingBytes > 0) - PRINT(2, this, "Still " << restingBytes << " to write!"); - } - else - { - if (!errorPrint) - PRINT(0, this, "ERROR: WriteFile Failed!"); - errorPrint = true; - } - } + while (restingBytes > 0) { + if (WriteFile(hFile, myPointer, restingBytes, &dwBytesWritten, nullptr) == TRUE) { + restingBytes -= dwBytesWritten; + myPointer = (void *)(((unsigned char *)myPointer) + dwBytesWritten); + if (restingBytes > 0) + PRINT(2, this, "Still " << restingBytes << " to write!"); + } else { + if (!errorPrint) + PRINT(0, this, "ERROR: WriteFile Failed!"); + errorPrint = true; + } + } } //----------------------------------------------------------------------------- @@ -127,38 +118,32 @@ void MiniMax::saveBytesToFile(HANDLE hFile, long long offset, unsigned int numBy //----------------------------------------------------------------------------- void MiniMax::loadBytesFromFile(HANDLE hFile, long long offset, unsigned int numBytes, void *pBytes) { - DWORD dwBytesRead; - LARGE_INTEGER liDistanceToMove; - unsigned int restingBytes = numBytes; - void *myPointer = pBytes; - bool errorPrint = false; + DWORD dwBytesRead; + LARGE_INTEGER liDistanceToMove; + unsigned int restingBytes = numBytes; + void *myPointer = pBytes; + bool errorPrint = false; - liDistanceToMove.QuadPart = offset; + liDistanceToMove.QuadPart = offset; - while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) - { - if (!errorPrint) - PRINT(0, this, "ERROR: SetFilePointerEx failed!"); - } + while (errorPrint = !SetFilePointerEx(hFile, liDistanceToMove, nullptr, FILE_BEGIN)) { + if (!errorPrint) + PRINT(0, this, "ERROR: SetFilePointerEx failed!"); + } - while (restingBytes > 0) - { - if (ReadFile(hFile, pBytes, restingBytes, &dwBytesRead, nullptr) == TRUE) - { - restingBytes -= dwBytesRead; - myPointer = (void *)(((unsigned char *)myPointer) + dwBytesRead); - if (restingBytes > 0) - { - PRINT(2, this, "Still " << restingBytes << " bytes to read!"); - } - } - else - { - if (!errorPrint) - PRINT(0, this, "ERROR: ReadFile Failed!"); - errorPrint = true; - } - } + while (restingBytes > 0) { + if (ReadFile(hFile, pBytes, restingBytes, &dwBytesRead, nullptr) == TRUE) { + restingBytes -= dwBytesRead; + myPointer = (void *)(((unsigned char *)myPointer) + dwBytesRead); + if (restingBytes > 0) { + PRINT(2, this, "Still " << restingBytes << " bytes to read!"); + } + } else { + if (!errorPrint) + PRINT(0, this, "ERROR: ReadFile Failed!"); + errorPrint = true; + } + } } //----------------------------------------------------------------------------- @@ -167,17 +152,14 @@ void MiniMax::loadBytesFromFile(HANDLE hFile, long long offset, unsigned int num //----------------------------------------------------------------------------- bool MiniMax::isCurrentStateInDatabase(unsigned int threadNo) { - unsigned int layerNum, stateNumber; + unsigned int layerNum, stateNumber; - if (hFileShortKnotValues == nullptr) - { - return false; - } - else - { - getLayerAndStateNumber(threadNo, layerNum, stateNumber); - return layerStats[layerNum].layerIsCompletedAndInFile; - } + if (hFileShortKnotValues == nullptr) { + return false; + } else { + getLayerAndStateNumber(threadNo, layerNum, stateNumber); + return layerStats[layerNum].layerIsCompletedAndInFile; + } } //----------------------------------------------------------------------------- @@ -186,10 +168,10 @@ bool MiniMax::isCurrentStateInDatabase(unsigned int threadNo) //----------------------------------------------------------------------------- void MiniMax::saveHeader(SkvFileHeader *dbH, LayerStats *lStats) { - DWORD dwBytesWritten; - SetFilePointer(hFileShortKnotValues, 0, nullptr, FILE_BEGIN); - WriteFile(hFileShortKnotValues, dbH, sizeof(SkvFileHeader), &dwBytesWritten, nullptr); - WriteFile(hFileShortKnotValues, lStats, sizeof(LayerStats) * dbH->numLayers, &dwBytesWritten, nullptr); + DWORD dwBytesWritten; + SetFilePointer(hFileShortKnotValues, 0, nullptr, FILE_BEGIN); + WriteFile(hFileShortKnotValues, dbH, sizeof(SkvFileHeader), &dwBytesWritten, nullptr); + WriteFile(hFileShortKnotValues, lStats, sizeof(LayerStats) * dbH->numLayers, &dwBytesWritten, nullptr); } //----------------------------------------------------------------------------- @@ -198,10 +180,10 @@ void MiniMax::saveHeader(SkvFileHeader *dbH, LayerStats *lStats) //----------------------------------------------------------------------------- void MiniMax::saveHeader(PlyInfoFileHeader *piH, PlyInfo *pInfo) { - DWORD dwBytesWritten; - SetFilePointer(hFilePlyInfo, 0, nullptr, FILE_BEGIN); - WriteFile(hFilePlyInfo, piH, sizeof(PlyInfoFileHeader), &dwBytesWritten, nullptr); - WriteFile(hFilePlyInfo, pInfo, sizeof(PlyInfo) * piH->numLayers, &dwBytesWritten, nullptr); + DWORD dwBytesWritten; + SetFilePointer(hFilePlyInfo, 0, nullptr, FILE_BEGIN); + WriteFile(hFilePlyInfo, piH, sizeof(PlyInfoFileHeader), &dwBytesWritten, nullptr); + WriteFile(hFilePlyInfo, pInfo, sizeof(PlyInfo) * piH->numLayers, &dwBytesWritten, nullptr); } //----------------------------------------------------------------------------- @@ -210,14 +192,13 @@ void MiniMax::saveHeader(PlyInfoFileHeader *piH, PlyInfo *pInfo) //----------------------------------------------------------------------------- bool MiniMax::openDatabase(const char *directory, unsigned int maximumNumberOfBranches) { - if (strlen(directory) && !PathFileExistsA(directory)) - { - PRINT(0, this, "ERROR: Database path " << directory << " not valid!"); - return falseOrStop(); - } - openSkvFile(directory, maximumNumberOfBranches); - openPlyInfoFile(directory); - return true; + if (strlen(directory) && !PathFileExistsA(directory)) { + PRINT(0, this, "ERROR: Database path " << directory << " not valid!"); + return falseOrStop(); + } + openSkvFile(directory, maximumNumberOfBranches); + openPlyInfoFile(directory); + return true; } //----------------------------------------------------------------------------- @@ -226,85 +207,78 @@ bool MiniMax::openDatabase(const char *directory, unsigned int maximumNumberOfBr //----------------------------------------------------------------------------- void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBranches) { - // locals - stringstream ssDatabaseFile; - DWORD dwBytesRead; - unsigned int i; + // locals + stringstream ssDatabaseFile; + DWORD dwBytesRead; + unsigned int i; - // don't open file twice - if (hFileShortKnotValues != nullptr) - return; + // don't open file twice + if (hFileShortKnotValues != nullptr) + return; - // remember directory name - fileDirectory.assign(directory); - ssDatabaseFile << fileDirectory << (strlen(directory) ? "\\" : "") << "shortKnotValue.dat"; - PRINT(2, this, "Open short knot value file: " << fileDirectory << (strlen(directory) ? "\\" : "") << "shortKnotValue.dat" << endl); + // remember directory name + fileDirectory.assign(directory); + ssDatabaseFile << fileDirectory << (strlen(directory) ? "\\" : "") << "shortKnotValue.dat"; + PRINT(2, this, "Open short knot value file: " << fileDirectory << (strlen(directory) ? "\\" : "") << "shortKnotValue.dat" << endl); - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hFileShortKnotValues = CreateFileA(ssDatabaseFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + 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 - if (hFileShortKnotValues == INVALID_HANDLE_VALUE) - { - hFileShortKnotValues = nullptr; - return; - } + // opened file succesfully + if (hFileShortKnotValues == INVALID_HANDLE_VALUE) { + hFileShortKnotValues = nullptr; + return; + } - // set header to invalid - skvfHeader.headerCode = 0; - maxNumBranches = maximumNumberOfBranches; + // set header to invalid + skvfHeader.headerCode = 0; + maxNumBranches = maximumNumberOfBranches; - // database complete ? - ReadFile(hFileShortKnotValues, &skvfHeader, sizeof(SkvFileHeader), &dwBytesRead, nullptr); + // database complete ? + ReadFile(hFileShortKnotValues, &skvfHeader, sizeof(SkvFileHeader), &dwBytesRead, nullptr); - // invalid file ? - if (dwBytesRead != sizeof(SkvFileHeader) || skvfHeader.headerCode != SKV_FILE_HEADER_CODE) - { + // invalid file ? + if (dwBytesRead != sizeof(SkvFileHeader) || skvfHeader.headerCode != SKV_FILE_HEADER_CODE) { - // create default header - skvfHeader.completed = false; - skvfHeader.numLayers = getNumberOfLayers(); - skvfHeader.headerCode = SKV_FILE_HEADER_CODE; - skvfHeader.headerAndStatsSize = sizeof(LayerStats) * skvfHeader.numLayers + sizeof(SkvFileHeader); - layerStats = new LayerStats[skvfHeader.numLayers]; - layerStats[0].layerOffset = 0; + // create default header + skvfHeader.completed = false; + skvfHeader.numLayers = getNumberOfLayers(); + skvfHeader.headerCode = SKV_FILE_HEADER_CODE; + skvfHeader.headerAndStatsSize = sizeof(LayerStats) * skvfHeader.numLayers + sizeof(SkvFileHeader); + layerStats = new LayerStats[skvfHeader.numLayers]; + layerStats[0].layerOffset = 0; - for (i = 0; i < skvfHeader.numLayers; i++) - { - getSuccLayers(i, &layerStats[i].numSuccLayers, &layerStats[i].succLayers[0]); - layerStats[i].partnerLayer = getPartnerLayer(i); - layerStats[i].knotsInLayer = getNumberOfKnotsInLayer(i); - layerStats[i].sizeInBytes = (layerStats[i].knotsInLayer + 3) / 4; - layerStats[i].shortKnotValueByte = nullptr; - layerStats[i].skvCompressed = nullptr; - layerStats[i].layerIsLoaded = false; - layerStats[i].layerIsCompletedAndInFile = false; - layerStats[i].numWonStates = 0; - layerStats[i].numLostStates = 0; - layerStats[i].numDrawnStates = 0; - layerStats[i].numInvalidStates = 0; - } + for (i = 0; i < skvfHeader.numLayers; i++) { + getSuccLayers(i, &layerStats[i].numSuccLayers, &layerStats[i].succLayers[0]); + layerStats[i].partnerLayer = getPartnerLayer(i); + layerStats[i].knotsInLayer = getNumberOfKnotsInLayer(i); + layerStats[i].sizeInBytes = (layerStats[i].knotsInLayer + 3) / 4; + layerStats[i].shortKnotValueByte = nullptr; + layerStats[i].skvCompressed = nullptr; + layerStats[i].layerIsLoaded = false; + layerStats[i].layerIsCompletedAndInFile = false; + layerStats[i].numWonStates = 0; + layerStats[i].numLostStates = 0; + layerStats[i].numDrawnStates = 0; + layerStats[i].numInvalidStates = 0; + } - for (i = 1; i < skvfHeader.numLayers; i++) - { - layerStats[i].layerOffset = layerStats[i - 1].layerOffset + layerStats[i - 1].sizeInBytes; - } + for (i = 1; i < skvfHeader.numLayers; i++) { + layerStats[i].layerOffset = layerStats[i - 1].layerOffset + layerStats[i - 1].sizeInBytes; + } - // write header - saveHeader(&skvfHeader, layerStats); + // write header + saveHeader(&skvfHeader, layerStats); - // read layer stats - } - else - { - layerStats = new LayerStats[skvfHeader.numLayers]; - ReadFile(hFileShortKnotValues, layerStats, sizeof(LayerStats) * skvfHeader.numLayers, &dwBytesRead, nullptr); - for (i = 0; i < skvfHeader.numLayers; i++) - { - layerStats[i].shortKnotValueByte = nullptr; - layerStats[i].skvCompressed = nullptr; - } - } + // read layer stats + } else { + layerStats = new LayerStats[skvfHeader.numLayers]; + ReadFile(hFileShortKnotValues, layerStats, sizeof(LayerStats) * skvfHeader.numLayers, &dwBytesRead, nullptr); + for (i = 0; i < skvfHeader.numLayers; i++) { + layerStats[i].shortKnotValueByte = nullptr; + layerStats[i].skvCompressed = nullptr; + } + } } //----------------------------------------------------------------------------- @@ -313,78 +287,71 @@ void MiniMax::openSkvFile(const char *directory, unsigned int maximumNumberOfBra //----------------------------------------------------------------------------- void MiniMax::openPlyInfoFile(const char *directory) { - // locals - stringstream ssFile; - DWORD dwBytesRead; - unsigned int i; + // locals + stringstream ssFile; + DWORD dwBytesRead; + unsigned int i; - // don't open file twice - if (hFilePlyInfo != nullptr) - return; + // don't open file twice + if (hFilePlyInfo != nullptr) + return; - // remember directory name - ssFile << directory << (strlen(directory) ? "\\" : "") << "plyInfo.dat"; - PRINT(2, this, "Open ply info file: " << ssFile.str() << endl - << endl); + // remember directory name + ssFile << directory << (strlen(directory) ? "\\" : "") << "plyInfo.dat"; + PRINT(2, this, "Open ply info file: " << ssFile.str() << endl + << endl); - // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) - hFilePlyInfo = CreateFileA(ssFile.str().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS) + 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 - if (hFilePlyInfo == INVALID_HANDLE_VALUE) - { - hFilePlyInfo = nullptr; - return; - } + // opened file succesfully + if (hFilePlyInfo == INVALID_HANDLE_VALUE) { + hFilePlyInfo = nullptr; + return; + } - // set header to invalid - plyInfoHeader.headerCode = 0; + // set header to invalid + plyInfoHeader.headerCode = 0; - // database complete ? - ReadFile(hFilePlyInfo, &plyInfoHeader, sizeof(plyInfoHeader), &dwBytesRead, nullptr); + // database complete ? + ReadFile(hFilePlyInfo, &plyInfoHeader, sizeof(plyInfoHeader), &dwBytesRead, nullptr); - // invalid file ? - if (dwBytesRead != sizeof(plyInfoHeader) || plyInfoHeader.headerCode != PLYINFO_HEADER_CODE) - { + // invalid file ? + if (dwBytesRead != sizeof(plyInfoHeader) || plyInfoHeader.headerCode != PLYINFO_HEADER_CODE) { - // create default header - plyInfoHeader.plyInfoCompleted = false; - plyInfoHeader.numLayers = getNumberOfLayers(); - plyInfoHeader.headerCode = PLYINFO_HEADER_CODE; - plyInfoHeader.headerAndPlyInfosSize = sizeof(PlyInfo) * plyInfoHeader.numLayers + sizeof(plyInfoHeader); - plyInfos = new PlyInfo[plyInfoHeader.numLayers]; - plyInfos[0].layerOffset = 0; + // create default header + plyInfoHeader.plyInfoCompleted = false; + plyInfoHeader.numLayers = getNumberOfLayers(); + plyInfoHeader.headerCode = PLYINFO_HEADER_CODE; + plyInfoHeader.headerAndPlyInfosSize = sizeof(PlyInfo) * plyInfoHeader.numLayers + sizeof(plyInfoHeader); + plyInfos = new PlyInfo[plyInfoHeader.numLayers]; + plyInfos[0].layerOffset = 0; - for (i = 0; i < plyInfoHeader.numLayers; i++) - { - plyInfos[i].knotsInLayer = getNumberOfKnotsInLayer(i); - plyInfos[i].plyInfo = nullptr; - plyInfos[i].plyInfoCompressed = nullptr; - plyInfos[i].plyInfoIsLoaded = false; - plyInfos[i].plyInfoIsCompletedAndInFile = false; - plyInfos[i].sizeInBytes = plyInfos[i].knotsInLayer * sizeof(PlyInfoVarType); - } + for (i = 0; i < plyInfoHeader.numLayers; i++) { + plyInfos[i].knotsInLayer = getNumberOfKnotsInLayer(i); + plyInfos[i].plyInfo = nullptr; + plyInfos[i].plyInfoCompressed = nullptr; + plyInfos[i].plyInfoIsLoaded = false; + plyInfos[i].plyInfoIsCompletedAndInFile = false; + plyInfos[i].sizeInBytes = plyInfos[i].knotsInLayer * sizeof(PlyInfoVarType); + } - for (i = 1; i < plyInfoHeader.numLayers; i++) - { - plyInfos[i].layerOffset = plyInfos[i - 1].layerOffset + plyInfos[i - 1].sizeInBytes; - } + for (i = 1; i < plyInfoHeader.numLayers; i++) { + plyInfos[i].layerOffset = plyInfos[i - 1].layerOffset + plyInfos[i - 1].sizeInBytes; + } - // write header - saveHeader(&plyInfoHeader, plyInfos); + // write header + saveHeader(&plyInfoHeader, plyInfos); - // read layer stats - } - else - { - plyInfos = new PlyInfo[plyInfoHeader.numLayers]; - ReadFile(hFilePlyInfo, plyInfos, sizeof(PlyInfo) * plyInfoHeader.numLayers, &dwBytesRead, nullptr); - for (i = 0; i < plyInfoHeader.numLayers; i++) - { - plyInfos[i].plyInfo = nullptr; - plyInfos[i].plyInfoCompressed = nullptr; - } - } + // read layer stats + } else { + plyInfos = new PlyInfo[plyInfoHeader.numLayers]; + ReadFile(hFilePlyInfo, plyInfos, sizeof(PlyInfo) * plyInfoHeader.numLayers, &dwBytesRead, nullptr); + for (i = 0; i < plyInfoHeader.numLayers; i++) { + plyInfos[i].plyInfo = nullptr; + plyInfos[i].plyInfoCompressed = nullptr; + } + } } //----------------------------------------------------------------------------- @@ -393,25 +360,24 @@ void MiniMax::openPlyInfoFile(const char *directory) //----------------------------------------------------------------------------- void MiniMax::saveLayerToFile(unsigned int layerNumber) { - // don't save layer and header when only preparing layers - PlyInfo *myPis = &plyInfos[layerNumber]; - LayerStats *myLss = &layerStats[layerNumber]; - if (onlyPrepareLayer) - return; + // don't save layer and header when only preparing layers + PlyInfo *myPis = &plyInfos[layerNumber]; + LayerStats *myLss = &layerStats[layerNumber]; + if (onlyPrepareLayer) + return; - // save layer if there are any states - if (myLss->sizeInBytes) - { + // save layer if there are any states + if (myLss->sizeInBytes) { - // short knot values & ply info - curCalculationActionId = MM_ACTION_SAVING_LAYER_TO_FILE; - saveBytesToFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte); - saveBytesToFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo); - } + // short knot values & ply info + curCalculationActionId = MM_ACTION_SAVING_LAYER_TO_FILE; + saveBytesToFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte); + saveBytesToFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo); + } - // mark layer as completed - myLss->layerIsCompletedAndInFile = true; - myPis->plyInfoIsCompletedAndInFile = true; + // mark layer as completed + myLss->layerIsCompletedAndInFile = true; + myPis->plyInfoIsCompletedAndInFile = true; } //----------------------------------------------------------------------------- @@ -420,35 +386,31 @@ void MiniMax::saveLayerToFile(unsigned int layerNumber) //----------------------------------------------------------------------------- inline void MiniMax::measureIops(long long &numOperations, LARGE_INTEGER &interval, LARGE_INTEGER &curTimeBefore, char text[]) { - // locals - LARGE_INTEGER curTimeAfter; + // locals + LARGE_INTEGER curTimeAfter; - if (!MEASURE_IOPS) - return; - numOperations++; // ... not thread-safe !!! + if (!MEASURE_IOPS) + return; + numOperations++; // ... not thread-safe !!! - // only the time for the io-operation is considered and accumulated - if (MEASURE_ONLY_IO) - { - QueryPerformanceCounter(&curTimeAfter); - interval.QuadPart += curTimeAfter.QuadPart - curTimeBefore.QuadPart; // ... not thread-safe !!! - double totalTimeGone = (double)interval.QuadPart / frequency.QuadPart; // ... not thread-safe !!! - if (totalTimeGone >= 5.0) - { - PRINT(0, this, text << "operations per second for last interval: " << (int)(numOperations / totalTimeGone)); - interval.QuadPart = 0; // ... not thread-safe !!! - numOperations = 0; // ... not thread-safe !!! - } - // the whole time passed since the beginning of the interval is considered - } - else if (numOperations >= MEASURE_TIME_FREQUENCY) - { - QueryPerformanceCounter(&curTimeAfter); - double totalTimeGone = (double)(curTimeAfter.QuadPart - interval.QuadPart) / frequency.QuadPart; // ... not thread-safe !!! - PRINT(0, this, text << "operations per second for last interval: " << numOperations / totalTimeGone); - interval.QuadPart = curTimeAfter.QuadPart; // ... not thread-safe !!! - numOperations = 0; // ... not thread-safe !!! - } + // only the time for the io-operation is considered and accumulated + if (MEASURE_ONLY_IO) { + QueryPerformanceCounter(&curTimeAfter); + interval.QuadPart += curTimeAfter.QuadPart - curTimeBefore.QuadPart; // ... not thread-safe !!! + double totalTimeGone = (double)interval.QuadPart / frequency.QuadPart; // ... not thread-safe !!! + if (totalTimeGone >= 5.0) { + PRINT(0, this, text << "operations per second for last interval: " << (int)(numOperations / totalTimeGone)); + interval.QuadPart = 0; // ... not thread-safe !!! + numOperations = 0; // ... not thread-safe !!! + } + // the whole time passed since the beginning of the interval is considered + } else if (numOperations >= MEASURE_TIME_FREQUENCY) { + QueryPerformanceCounter(&curTimeAfter); + double totalTimeGone = (double)(curTimeAfter.QuadPart - interval.QuadPart) / frequency.QuadPart; // ... not thread-safe !!! + PRINT(0, this, text << "operations per second for last interval: " << numOperations / totalTimeGone); + interval.QuadPart = curTimeAfter.QuadPart; // ... not thread-safe !!! + numOperations = 0; // ... not thread-safe !!! + } } //----------------------------------------------------------------------------- @@ -457,31 +419,27 @@ inline void MiniMax::measureIops(long long &numOperations, LARGE_INTEGER &interv //----------------------------------------------------------------------------- void MiniMax::readKnotValueFromDatabase(unsigned int threadNo, unsigned int &layerNumber, unsigned int &stateNumber, TwoBit &knotValue, bool &invalidLayerOrStateNumber, bool &layerInDatabaseAndCompleted) { - // get state number, since this is the address, where the value is saved - getLayerAndStateNumber(threadNo, layerNumber, stateNumber); + // get state number, since this is the address, where the value is saved + getLayerAndStateNumber(threadNo, layerNumber, stateNumber); - // layer in database and completed ? - LayerStats *myLss = &layerStats[layerNumber]; - layerInDatabaseAndCompleted = myLss->layerIsCompletedAndInFile; + // layer in database and completed ? + LayerStats *myLss = &layerStats[layerNumber]; + layerInDatabaseAndCompleted = myLss->layerIsCompletedAndInFile; - // valid state and layer number ? - if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) - { - invalidLayerOrStateNumber = true; - } - else - { - invalidLayerOrStateNumber = false; // checkStateIntegrity(); - } + // valid state and layer number ? + if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) { + invalidLayerOrStateNumber = true; + } else { + invalidLayerOrStateNumber = false; // checkStateIntegrity(); + } - if (invalidLayerOrStateNumber) - { - knotValue = SKV_VALUE_INVALID; - return; - } + if (invalidLayerOrStateNumber) { + knotValue = SKV_VALUE_INVALID; + return; + } - // read - readKnotValueFromDatabase(layerNumber, stateNumber, knotValue); + // read + readKnotValueFromDatabase(layerNumber, stateNumber, knotValue); } //----------------------------------------------------------------------------- @@ -490,74 +448,64 @@ void MiniMax::readKnotValueFromDatabase(unsigned int threadNo, unsigned int &lay //----------------------------------------------------------------------------- void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit &knotValue) { - // locals - TwoBit databaseByte; - long long bytesAllocated; - TwoBit defValue = SKV_WHOLE_BYTE_IS_INVALID; - LayerStats *myLss = &layerStats[layerNumber]; + // locals + TwoBit databaseByte; + long long bytesAllocated; + TwoBit defValue = SKV_WHOLE_BYTE_IS_INVALID; + LayerStats *myLss = &layerStats[layerNumber]; - // valid state and layer number ? - if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) - { - PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readKnotValueFromDatabase()!"); - knotValue = SKV_VALUE_INVALID; - return; - } + // valid state and layer number ? + if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) { + PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readKnotValueFromDatabase()!"); + knotValue = SKV_VALUE_INVALID; + return; + } - // if database is complete get whole byte from file - if (skvfHeader.completed || layerInDatabase || myLss->layerIsCompletedAndInFile) - { - EnterCriticalSection(&csDatabase); - loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset + stateNumber / 4, 1, &databaseByte); - LeaveCriticalSection(&csDatabase); - } - else - { + // if database is complete get whole byte from file + if (skvfHeader.completed || layerInDatabase || myLss->layerIsCompletedAndInFile) { + EnterCriticalSection(&csDatabase); + loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset + stateNumber / 4, 1, &databaseByte); + LeaveCriticalSection(&csDatabase); + } else { - // is layer already loaded - if (!myLss->layerIsLoaded) - { + // is layer already loaded + if (!myLss->layerIsLoaded) { - EnterCriticalSection(&csDatabase); - if (!myLss->layerIsLoaded) - { - // 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]; - if (myLss->layerIsCompletedAndInFile) - { - loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte); - } - else - { - memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); - } - bytesAllocated = myLss->sizeInBytes; - arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); + EnterCriticalSection(&csDatabase); + if (!myLss->layerIsLoaded) { + // 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]; + if (myLss->layerIsCompletedAndInFile) { + loadBytesFromFile(hFileShortKnotValues, skvfHeader.headerAndStatsSize + myLss->layerOffset, myLss->sizeInBytes, myLss->shortKnotValueByte); + } else { + memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); + } + bytesAllocated = myLss->sizeInBytes; + arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); - // output - myLss->layerIsLoaded = true; - memoryUsed2 += bytesAllocated; - PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for knot values of layer " << layerNumber << ", which is " << (myLss->layerIsCompletedAndInFile ? "" : " NOT ") << " fully calculated, due to read operation."); - } - LeaveCriticalSection(&csDatabase); - } + // output + myLss->layerIsLoaded = true; + memoryUsed2 += bytesAllocated; + PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for knot values of layer " << layerNumber << ", which is " << (myLss->layerIsCompletedAndInFile ? "" : " NOT ") << " fully calculated, due to read operation."); + } + LeaveCriticalSection(&csDatabase); + } - // measure io-operations per second - LARGE_INTEGER curTimeBefore; - if (MEASURE_IOPS && MEASURE_ONLY_IO) - { - QueryPerformanceCounter(&curTimeBefore); - } + // measure io-operations per second + LARGE_INTEGER curTimeBefore; + if (MEASURE_IOPS && MEASURE_ONLY_IO) { + QueryPerformanceCounter(&curTimeBefore); + } - // read ply info from array - databaseByte = myLss->shortKnotValueByte[stateNumber / 4]; + // read ply info from array + databaseByte = myLss->shortKnotValueByte[stateNumber / 4]; - // measure io-operations per second - measureIops(numReadSkvOperations, readSkvInterval, curTimeBefore, "Read knot value "); - } + // measure io-operations per second + measureIops(numReadSkvOperations, readSkvInterval, curTimeBefore, "Read knot value "); + } - // make half byte - knotValue = _rotr8(databaseByte, 2 * (stateNumber % 4)) & 3; + // make half byte + knotValue = _rotr8(databaseByte, 2 * (stateNumber % 4)) & 3; } //----------------------------------------------------------------------------- @@ -566,71 +514,60 @@ void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int s //----------------------------------------------------------------------------- void MiniMax::readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType &value) { - // locals - unsigned int curKnot; - PlyInfoVarType defValue = PLYINFO_VALUE_UNCALCULATED; - long long bytesAllocated; - PlyInfo *myPis = &plyInfos[layerNumber]; + // locals + unsigned int curKnot; + PlyInfoVarType defValue = PLYINFO_VALUE_UNCALCULATED; + long long bytesAllocated; + PlyInfo *myPis = &plyInfos[layerNumber]; - // valid state and layer number ? - if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) - { - PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readPlyInfoFromDatabase()!"); - value = PLYINFO_VALUE_INVALID; - return; - } + // valid state and layer number ? + if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) { + PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in readPlyInfoFromDatabase()!"); + value = PLYINFO_VALUE_INVALID; + return; + } - // if database is complete get whole byte from file - if (plyInfoHeader.plyInfoCompleted || layerInDatabase || myPis->plyInfoIsCompletedAndInFile) - { - EnterCriticalSection(&csDatabase); - loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset + sizeof(PlyInfoVarType) * stateNumber, sizeof(PlyInfoVarType), &value); - LeaveCriticalSection(&csDatabase); - } - else - { + // if database is complete get whole byte from file + if (plyInfoHeader.plyInfoCompleted || layerInDatabase || myPis->plyInfoIsCompletedAndInFile) { + EnterCriticalSection(&csDatabase); + loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset + sizeof(PlyInfoVarType) * stateNumber, sizeof(PlyInfoVarType), &value); + LeaveCriticalSection(&csDatabase); + } else { - // is layer already in memory? - if (!myPis->plyInfoIsLoaded) - { - EnterCriticalSection(&csDatabase); - if (!myPis->plyInfoIsLoaded) - { - // if layer is in database and completed, then load layer from file into memory; set default value otherwise - myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; - if (myPis->plyInfoIsCompletedAndInFile) - { - loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo); - } - else - { - for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) - { - myPis->plyInfo[curKnot] = defValue; - } - } - bytesAllocated = myPis->sizeInBytes; - arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); - myPis->plyInfoIsLoaded = true; - memoryUsed2 += bytesAllocated; - PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for ply info of layer " << layerNumber << ", which is " << (myPis->plyInfoIsCompletedAndInFile ? "" : " NOT ") << " fully calculated, due to read operation."); - } - LeaveCriticalSection(&csDatabase); - } + // is layer already in memory? + if (!myPis->plyInfoIsLoaded) { + EnterCriticalSection(&csDatabase); + if (!myPis->plyInfoIsLoaded) { + // if layer is in database and completed, then load layer from file into memory; set default value otherwise + myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; + if (myPis->plyInfoIsCompletedAndInFile) { + loadBytesFromFile(hFilePlyInfo, plyInfoHeader.headerAndPlyInfosSize + myPis->layerOffset, myPis->sizeInBytes, myPis->plyInfo); + } else { + for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) { + myPis->plyInfo[curKnot] = defValue; + } + } + bytesAllocated = myPis->sizeInBytes; + arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); + myPis->plyInfoIsLoaded = true; + memoryUsed2 += bytesAllocated; + PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for ply info of layer " << layerNumber << ", which is " << (myPis->plyInfoIsCompletedAndInFile ? "" : " NOT ") << " fully calculated, due to read operation."); + } + LeaveCriticalSection(&csDatabase); + } - // measure io-operations per second - LARGE_INTEGER curTimeBefore; - if (MEASURE_IOPS && MEASURE_ONLY_IO) - { - QueryPerformanceCounter(&curTimeBefore); - } + // measure io-operations per second + LARGE_INTEGER curTimeBefore; + if (MEASURE_IOPS && MEASURE_ONLY_IO) { + QueryPerformanceCounter(&curTimeBefore); + } - // read ply info from array - value = myPis->plyInfo[stateNumber]; + // read ply info from array + value = myPis->plyInfo[stateNumber]; - // measure io-operations per second - measureIops(numReadPlyOperations, readPlyInterval, curTimeBefore, "Read ply info "); - } + // measure io-operations per second + measureIops(numReadPlyOperations, readPlyInterval, curTimeBefore, "Read ply info "); + } } //----------------------------------------------------------------------------- @@ -639,67 +576,61 @@ void MiniMax::readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int sta //----------------------------------------------------------------------------- void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue) { - // locals - long long bytesAllocated; - TwoBit defValue = SKV_WHOLE_BYTE_IS_INVALID; - LayerStats *myLss = &layerStats[layerNumber]; + // locals + long long bytesAllocated; + TwoBit defValue = SKV_WHOLE_BYTE_IS_INVALID; + LayerStats *myLss = &layerStats[layerNumber]; - // valid state and layer number ? - if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) - { - PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in saveKnotValueInDatabase()!"); - return; - } + // valid state and layer number ? + if (layerNumber > skvfHeader.numLayers || stateNumber > myLss->knotsInLayer) { + PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in saveKnotValueInDatabase()!"); + return; + } - // is layer already completed ? - if (myLss->layerIsCompletedAndInFile) - { - PRINT(0, this, "ERROR: layer already completed and in file! function: saveKnotValueInDatabase()!"); - return; - } + // is layer already completed ? + if (myLss->layerIsCompletedAndInFile) { + PRINT(0, this, "ERROR: layer already completed and in file! function: saveKnotValueInDatabase()!"); + return; + } - // is layer already loaded? - if (!myLss->layerIsLoaded) - { + // is layer already loaded? + if (!myLss->layerIsLoaded) { - EnterCriticalSection(&csDatabase); - if (!myLss->layerIsLoaded) - { - // reserve memory for this layer & create array for ply info with default value - myLss->shortKnotValueByte = new TwoBit[myLss->sizeInBytes]; - memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); - bytesAllocated = myLss->sizeInBytes; - arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); + EnterCriticalSection(&csDatabase); + if (!myLss->layerIsLoaded) { + // reserve memory for this layer & create array for ply info with default value + myLss->shortKnotValueByte = new TwoBit[myLss->sizeInBytes]; + memset(myLss->shortKnotValueByte, SKV_WHOLE_BYTE_IS_INVALID, myLss->sizeInBytes); + bytesAllocated = myLss->sizeInBytes; + arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_layerStats, myLss->sizeInBytes, 0); - // output - memoryUsed2 += bytesAllocated; - PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for knot values of layer " << layerNumber << " due to write operation!"); - myLss->layerIsLoaded = true; - } - LeaveCriticalSection(&csDatabase); - } + // output + memoryUsed2 += bytesAllocated; + PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for knot values of layer " << layerNumber << " due to write operation!"); + myLss->layerIsLoaded = true; + } + LeaveCriticalSection(&csDatabase); + } - // measure io-operations per second - LARGE_INTEGER curTimeBefore; - if (MEASURE_IOPS && MEASURE_ONLY_IO) - { - QueryPerformanceCounter(&curTimeBefore); - } + // measure io-operations per second + LARGE_INTEGER curTimeBefore; + if (MEASURE_IOPS && MEASURE_ONLY_IO) { + QueryPerformanceCounter(&curTimeBefore); + } - // set value - long *pShortKnotValue = ((long *)myLss->shortKnotValueByte) + stateNumber / ((sizeof(long) * 8) / 2); - long numBitsToShift = 2 * (stateNumber % ((sizeof(long) * 8) / 2)); // little-endian byte-order - long mask = 0x00000003 << numBitsToShift; - long curShortKnotValueLong, newShortKnotValueLong; + // set value + long *pShortKnotValue = ((long *)myLss->shortKnotValueByte) + stateNumber / ((sizeof(long) * 8) / 2); + long numBitsToShift = 2 * (stateNumber % ((sizeof(long) * 8) / 2)); // little-endian byte-order + long mask = 0x00000003 << numBitsToShift; + long curShortKnotValueLong, newShortKnotValueLong; - do - { - curShortKnotValueLong = *pShortKnotValue; - newShortKnotValueLong = (curShortKnotValueLong & (~mask)) + (knotValue << numBitsToShift); - } while (InterlockedCompareExchange(pShortKnotValue, newShortKnotValueLong, curShortKnotValueLong) != curShortKnotValueLong); + do { + curShortKnotValueLong = *pShortKnotValue; + newShortKnotValueLong = (curShortKnotValueLong & (~mask)) + (knotValue << numBitsToShift); + } while (InterlockedCompareExchange(pShortKnotValue, newShortKnotValueLong, curShortKnotValueLong) != curShortKnotValueLong); - // measure io-operations per second - measureIops(numWriteSkvOperations, writeSkvInterval, curTimeBefore, "Write knot value "); + // measure io-operations per second + measureIops(numWriteSkvOperations, writeSkvInterval, curTimeBefore, "Write knot value "); } //----------------------------------------------------------------------------- @@ -708,58 +639,52 @@ void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int sta //----------------------------------------------------------------------------- void MiniMax::savePlyInfoInDatabase(unsigned int layerNumber, unsigned int stateNumber, PlyInfoVarType value) { - // locals - unsigned int curKnot; - PlyInfoVarType defValue = PLYINFO_VALUE_UNCALCULATED; - long long bytesAllocated; - PlyInfo *myPis = &plyInfos[layerNumber]; + // locals + unsigned int curKnot; + PlyInfoVarType defValue = PLYINFO_VALUE_UNCALCULATED; + long long bytesAllocated; + PlyInfo *myPis = &plyInfos[layerNumber]; - // valid state and layer number ? - if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) - { - PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in savePlyInfoInDatabase()!"); - return; - } + // valid state and layer number ? + if (layerNumber > plyInfoHeader.numLayers || stateNumber > myPis->knotsInLayer) { + PRINT(0, this, "ERROR: INVALID layerNumber OR stateNumber in savePlyInfoInDatabase()!"); + return; + } - // is layer already completed ? - if (myPis->plyInfoIsCompletedAndInFile) - { - PRINT(0, this, "ERROR: layer already completed and in file! function: savePlyInfoInDatabase()!"); - return; - } + // is layer already completed ? + if (myPis->plyInfoIsCompletedAndInFile) { + PRINT(0, this, "ERROR: layer already completed and in file! function: savePlyInfoInDatabase()!"); + return; + } - // is layer already loaded - if (!myPis->plyInfoIsLoaded) - { + // is layer already loaded + if (!myPis->plyInfoIsLoaded) { - EnterCriticalSection(&csDatabase); - if (!myPis->plyInfoIsLoaded) - { - // reserve memory for this layer & create array for ply info with default value - myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; - for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) - { - myPis->plyInfo[curKnot] = defValue; - } - bytesAllocated = myPis->sizeInBytes; - arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); - myPis->plyInfoIsLoaded = true; - memoryUsed2 += bytesAllocated; - PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for ply info of layer " << layerNumber << " due to write operation!"); - } - LeaveCriticalSection(&csDatabase); - } + EnterCriticalSection(&csDatabase); + if (!myPis->plyInfoIsLoaded) { + // reserve memory for this layer & create array for ply info with default value + myPis->plyInfo = new PlyInfoVarType[myPis->knotsInLayer]; + for (curKnot = 0; curKnot < myPis->knotsInLayer; curKnot++) { + myPis->plyInfo[curKnot] = defValue; + } + bytesAllocated = myPis->sizeInBytes; + arrayInfos.addArray(layerNumber, ArrayInfo::arrayType_plyInfos, myPis->sizeInBytes, 0); + myPis->plyInfoIsLoaded = true; + memoryUsed2 += bytesAllocated; + PRINT(3, this, "Allocated " << bytesAllocated << " bytes in memory for ply info of layer " << layerNumber << " due to write operation!"); + } + LeaveCriticalSection(&csDatabase); + } - // measure io-operations per second - LARGE_INTEGER curTimeBefore; - if (MEASURE_IOPS && MEASURE_ONLY_IO) - { - QueryPerformanceCounter(&curTimeBefore); - } + // measure io-operations per second + LARGE_INTEGER curTimeBefore; + if (MEASURE_IOPS && MEASURE_ONLY_IO) { + QueryPerformanceCounter(&curTimeBefore); + } - // set value - myPis->plyInfo[stateNumber] = value; + // set value + myPis->plyInfo[stateNumber] = value; - // measure io-operations per second - measureIops(numWritePlyOperations, writePlyInterval, curTimeBefore, "Write ply info "); + // measure io-operations per second + measureIops(numWritePlyOperations, writePlyInterval, curTimeBefore, "Write ply info "); } diff --git a/src/perfect/miniMax_retroAnalysis.cpp b/src/perfect/miniMax_retroAnalysis.cpp index 543d1522..84de8095 100644 --- a/src/perfect/miniMax_retroAnalysis.cpp +++ b/src/perfect/miniMax_retroAnalysis.cpp @@ -1,9 +1,9 @@ /********************************************************************* - miniMax_retroAnalysis.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax_retroAnalysis.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp s\*********************************************************************/ #include "miniMax.h" @@ -19,105 +19,94 @@ s\*********************************************************************/ //----------------------------------------------------------------------------- bool MiniMax::calcKnotValuesByRetroAnalysis(vector &layersToCalculate) { - // locals - bool abortCalculation = false; - unsigned int curLayer = 0; // Counter variable - unsigned int curSubLayer = 0; // Counter variable - unsigned int plyCounter = 0; // Counter variable - unsigned int threadNo; - stringstream ssLayers; - retroAnalysisGlobalVars retroVars; + // locals + bool abortCalculation = false; + unsigned int curLayer = 0; // Counter variable + unsigned int curSubLayer = 0; // Counter variable + unsigned int plyCounter = 0; // Counter variable + unsigned int threadNo; + stringstream ssLayers; + retroAnalysisGlobalVars retroVars; - // init retro vars - retroVars.thread.resize(threadManager.getNumThreads()); - for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) - { - retroVars.thread[threadNo].statesToProcess.resize(PLYINFO_EXP_VALUE, nullptr); - retroVars.thread[threadNo].numStatesToProcess = 0; - retroVars.thread[threadNo].threadNo = threadNo; - } - retroVars.countArrays.resize(layersToCalculate.size(), nullptr); - retroVars.layerInitialized.resize(skvfHeader.numLayers, false); - retroVars.layersToCalculate = layersToCalculate; - retroVars.pMiniMax = this; - for (retroVars.totalNumKnots = 0, retroVars.numKnotsToCalc = 0, curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) - { - retroVars.numKnotsToCalc += layerStats[layersToCalculate[curLayer]].knotsInLayer; - retroVars.totalNumKnots += layerStats[layersToCalculate[curLayer]].knotsInLayer; - retroVars.layerInitialized[layersToCalculate[curLayer]] = true; - for (curSubLayer = 0; curSubLayer < layerStats[layersToCalculate[curLayer]].numSuccLayers; curSubLayer++) - { - if (retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]]) - continue; - else - retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]] = true; - retroVars.totalNumKnots += layerStats[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]].knotsInLayer; - } - } - retroVars.layerInitialized.assign(skvfHeader.numLayers, false); + // init retro vars + retroVars.thread.resize(threadManager.getNumThreads()); + for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) { + retroVars.thread[threadNo].statesToProcess.resize(PLYINFO_EXP_VALUE, nullptr); + retroVars.thread[threadNo].numStatesToProcess = 0; + retroVars.thread[threadNo].threadNo = threadNo; + } + retroVars.countArrays.resize(layersToCalculate.size(), nullptr); + retroVars.layerInitialized.resize(skvfHeader.numLayers, false); + retroVars.layersToCalculate = layersToCalculate; + retroVars.pMiniMax = this; + for (retroVars.totalNumKnots = 0, retroVars.numKnotsToCalc = 0, curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) { + retroVars.numKnotsToCalc += layerStats[layersToCalculate[curLayer]].knotsInLayer; + retroVars.totalNumKnots += layerStats[layersToCalculate[curLayer]].knotsInLayer; + retroVars.layerInitialized[layersToCalculate[curLayer]] = true; + for (curSubLayer = 0; curSubLayer < layerStats[layersToCalculate[curLayer]].numSuccLayers; curSubLayer++) { + if (retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]]) + continue; + else + retroVars.layerInitialized[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]] = true; + retroVars.totalNumKnots += layerStats[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]].knotsInLayer; + } + } + retroVars.layerInitialized.assign(skvfHeader.numLayers, false); - // output & filenames - for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) - ssLayers << " " << layersToCalculate[curLayer]; - PRINT(0, this, "*** Calculate layers" << ssLayers.str() << " by retro analysis ***"); + // output & filenames + for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) + ssLayers << " " << layersToCalculate[curLayer]; + PRINT(0, this, "*** Calculate layers" << ssLayers.str() << " by retro analysis ***"); - // initialization - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - if (!initRetroAnalysis(retroVars)) - { - abortCalculation = true; - goto freeMem; - } + // initialization + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + if (!initRetroAnalysis(retroVars)) { + abortCalculation = true; + goto freeMem; + } - // prepare count arrays - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - if (!prepareCountArrays(retroVars)) - { - abortCalculation = true; - goto freeMem; - } + // prepare count arrays + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + if (!prepareCountArrays(retroVars)) { + abortCalculation = true; + goto freeMem; + } - // stop here if only preparing layer - if (onlyPrepareLayer) - goto freeMem; + // stop here if only preparing layer + if (onlyPrepareLayer) + goto freeMem; - // iteration - PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); - if (!performRetroAnalysis(retroVars)) - { - abortCalculation = true; - goto freeMem; - } + // iteration + PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl); + if (!performRetroAnalysis(retroVars)) { + abortCalculation = true; + goto freeMem; + } - // show output - PRINT(2, this, " Bytes in memory: " << memoryUsed2); - for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) - { - showLayerStats(layersToCalculate[curLayer]); - } - PRINT(2, this, ""); + // show output + PRINT(2, this, " Bytes in memory: " << memoryUsed2); + for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) { + showLayerStats(layersToCalculate[curLayer]); + } + PRINT(2, this, ""); - // free memory + // free memory freeMem: - for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) - { - for (plyCounter = 0; plyCounter < retroVars.thread[threadNo].statesToProcess.size(); plyCounter++) - { - SAFE_DELETE(retroVars.thread[threadNo].statesToProcess[plyCounter]); - } - } - for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) - { - if (retroVars.countArrays[curLayer] != nullptr) - { - memoryUsed2 -= layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType); - arrayInfos.removeArray(layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType), 0); - } - SAFE_DELETE_ARRAY(retroVars.countArrays[curLayer]); - } - if (!abortCalculation) - PRINT(2, this, " Bytes in memory: " << memoryUsed2); - return !abortCalculation; + for (threadNo = 0; threadNo < threadManager.getNumThreads(); threadNo++) { + for (plyCounter = 0; plyCounter < retroVars.thread[threadNo].statesToProcess.size(); plyCounter++) { + SAFE_DELETE(retroVars.thread[threadNo].statesToProcess[plyCounter]); + } + } + for (curLayer = 0; curLayer < layersToCalculate.size(); curLayer++) { + if (retroVars.countArrays[curLayer] != nullptr) { + memoryUsed2 -= layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType); + arrayInfos.removeArray(layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, layerStats[layersToCalculate[curLayer]].knotsInLayer * sizeof(CountArrayVarType), 0); + } + SAFE_DELETE_ARRAY(retroVars.countArrays[curLayer]); + } + if (!abortCalculation) + PRINT(2, this, " Bytes in memory: " << memoryUsed2); + return !abortCalculation; } //----------------------------------------------------------------------------- @@ -126,85 +115,82 @@ freeMem: //----------------------------------------------------------------------------- bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars) { - // locals - unsigned int curLayerId; // current processed layer within 'layersToCalculate' - unsigned int layerNumber; // layer number of the current process layer - stringstream ssInitArrayPath; // path of the working directory - stringstream ssInitArrayFilePath; // filename corresponding to a cyclic array file which is used for storage - BufferedFile *initArray; // - bool initAlreadyDone = false; // true if the initialization information is already available in a file + // locals + unsigned int curLayerId; // current processed layer within 'layersToCalculate' + unsigned int layerNumber; // layer number of the current process layer + stringstream ssInitArrayPath; // path of the working directory + stringstream ssInitArrayFilePath; // filename corresponding to a cyclic array file which is used for storage + BufferedFile *initArray; // + bool initAlreadyDone = false; // true if the initialization information is already available in a file - // process each layer - for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) - { + // process each layer + for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) { - // set current processed layer number - layerNumber = retroVars.layersToCalculate[curLayerId]; - curCalculationActionId = MM_ACTION_INIT_RETRO_ANAL; - PRINT(1, this, endl << " *** Initialization of layer " << layerNumber << " (" << (getOutputInformation(layerNumber)) << ") which has " << layerStats[layerNumber].knotsInLayer << " knots ***"); + // set current processed layer number + layerNumber = retroVars.layersToCalculate[curLayerId]; + curCalculationActionId = MM_ACTION_INIT_RETRO_ANAL; + PRINT(1, this, endl << " *** Initialization of layer " << layerNumber << " (" << (getOutputInformation(layerNumber)) << ") which has " << layerStats[layerNumber].knotsInLayer << " knots ***"); - // file names - ssInitArrayPath.str(""); - ssInitArrayPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "initLayer"; - ssInitArrayFilePath.str(""); - ssInitArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "initLayer\\initLayer" << layerNumber << ".dat"; + // file names + ssInitArrayPath.str(""); + ssInitArrayPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "initLayer"; + ssInitArrayFilePath.str(""); + ssInitArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "initLayer\\initLayer" << layerNumber << ".dat"; - // does initialization file exist ? - CreateDirectoryA(ssInitArrayPath.str().c_str(), nullptr); - initArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInitArrayFilePath.str().c_str()); - if (initArray->getFileSize() == (LONGLONG)layerStats[layerNumber].knotsInLayer) - { - PRINT(2, this, " Loading init states from file: " << ssInitArrayFilePath.str()); - initAlreadyDone = true; - } + // does initialization file exist ? + CreateDirectoryA(ssInitArrayPath.str().c_str(), nullptr); + initArray = new BufferedFile(threadManager.getNumThreads(), FILE_BUFFER_SIZE, ssInitArrayFilePath.str().c_str()); + if (initArray->getFileSize() == (LONGLONG)layerStats[layerNumber].knotsInLayer) { + PRINT(2, this, " Loading init states from file: " << ssInitArrayFilePath.str()); + initAlreadyDone = true; + } - // don't add layers twice - if (retroVars.layerInitialized[layerNumber]) - continue; - else - retroVars.layerInitialized[layerNumber] = true; + // don't add layers twice + if (retroVars.layerInitialized[layerNumber]) + continue; + else + retroVars.layerInitialized[layerNumber] = true; - // prepare parameters - numStatesProcessed = 0; - retroVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; - retroVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; - retroVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; - retroVars.statsValueCounter[SKV_VALUE_INVALID] = 0; - ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), InitRetroAnalysisVars(this, &retroVars, layerNumber, initArray, initAlreadyDone)); + // prepare parameters + numStatesProcessed = 0; + retroVars.statsValueCounter[SKV_VALUE_GAME_WON] = 0; + retroVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0; + retroVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0; + retroVars.statsValueCounter[SKV_VALUE_INVALID] = 0; + ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), InitRetroAnalysisVars(this, &retroVars, layerNumber, initArray, initAlreadyDone)); - // process each state in the current layer - switch (threadManager.executeParallelLoop(initRetroAnalysisThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - SAFE_DELETE(initArray); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // process each state in the current layer + switch (threadManager.executeParallelLoop(initRetroAnalysisThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + SAFE_DELETE(initArray); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // reduce and delete thread specific data - tva.reduce(); - initAlreadyDone = false; - initArray->flushBuffers(); - SAFE_DELETE(initArray); - if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) - return falseOrStop(); + // reduce and delete thread specific data + tva.reduce(); + initAlreadyDone = false; + initArray->flushBuffers(); + SAFE_DELETE(initArray); + if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) + return falseOrStop(); - // when init file was created new then save it now - PRINT(2, this, " Saved initialized states to file: " << ssInitArrayFilePath.str()); + // when init file was created new then save it now + PRINT(2, this, " Saved initialized states to file: " << ssInitArrayFilePath.str()); - // show statistics - PRINT(2, this, " won states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_WON]); - PRINT(2, this, " lost states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_LOST]); - PRINT(2, this, " draw states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); - PRINT(2, this, " invalid states: " << retroVars.statsValueCounter[SKV_VALUE_INVALID]); - } - return true; + // show statistics + PRINT(2, this, " won states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_WON]); + PRINT(2, this, " lost states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_LOST]); + PRINT(2, this, " draw states: " << retroVars.statsValueCounter[SKV_VALUE_GAME_DRAWN]); + PRINT(2, this, " invalid states: " << retroVars.statsValueCounter[SKV_VALUE_INVALID]); + } + return true; } //----------------------------------------------------------------------------- @@ -213,82 +199,70 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars) //----------------------------------------------------------------------------- DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index) { - // locals - InitRetroAnalysisVars *iraVars = (InitRetroAnalysisVars *)pParameter; - MiniMax *m = iraVars->pMiniMax; - float floatValue; // dummy variable for calls of getValueOfSituation() - StateAdress curState; // current state counter for loops - TwoBit curStateValue; // for calls of getValueOfSituation() + // locals + InitRetroAnalysisVars *iraVars = (InitRetroAnalysisVars *)pParameter; + MiniMax *m = iraVars->pMiniMax; + float floatValue; // dummy variable for calls of getValueOfSituation() + StateAdress curState; // current state counter for loops + TwoBit curStateValue; // for calls of getValueOfSituation() - curState.layerNumber = iraVars->layerNumber; - curState.stateNumber = index; - iraVars->statesProcessed++; + curState.layerNumber = iraVars->layerNumber; + curState.stateNumber = index; + iraVars->statesProcessed++; - // print status - if (iraVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(2, m, "Already initialized " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); - } + // print status + if (iraVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_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 - if (iraVars->initAlreadyDone) - { - if (!iraVars->bufferedFile->readBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) - { - PRINT(0, m, "ERROR: initArray->takeBytes() failed"); - return m->falseOrStop(); - } + // layer initialization already done ? if so, then read from file + if (iraVars->initAlreadyDone) { + if (!iraVars->bufferedFile->readBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) { + PRINT(0, m, "ERROR: initArray->takeBytes() failed"); + return m->falseOrStop(); + } - // initialization not done - } - else - { + // initialization not done + } else { - // set current selected situation - if (!m->setSituation(iraVars->curThreadNo, curState.layerNumber, curState.stateNumber)) - { - curStateValue = SKV_VALUE_INVALID; - } - else - { - // get value of current situation - m->getValueOfSituation(iraVars->curThreadNo, floatValue, curStateValue); - } - } + // set current selected situation + if (!m->setSituation(iraVars->curThreadNo, curState.layerNumber, curState.stateNumber)) { + curStateValue = SKV_VALUE_INVALID; + } else { + // get value of current situation + m->getValueOfSituation(iraVars->curThreadNo, floatValue, curStateValue); + } + } - // save init value - if (curStateValue != SKV_VALUE_INVALID) - { + // save init value + if (curStateValue != SKV_VALUE_INVALID) { - // save short knot value - m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + // save short knot value + m->saveKnotValueInDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - // put in list if state is final - if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) - { + // put in list if state is final + if (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST) { - // ply info - m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, 0); + // ply info + m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, 0); - // add state to list - m->addStateToProcessQueue(*iraVars->retroVars, iraVars->retroVars->thread[iraVars->curThreadNo], 0, &curState); - } - } + // add state to list + m->addStateToProcessQueue(*iraVars->retroVars, iraVars->retroVars->thread[iraVars->curThreadNo], 0, &curState); + } + } - // write data to file - if (!iraVars->initAlreadyDone) - { - // curStateValue sollte 2 sein bei index == 1329322 - if (!iraVars->bufferedFile->writeBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) - { - PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); - return m->falseOrStop(); - } - } - iraVars->statsValueCounter[curStateValue]++; + // write data to file + if (!iraVars->initAlreadyDone) { + // curStateValue sollte 2 sein bei index == 1329322 + if (!iraVars->bufferedFile->writeBytes(iraVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) { + PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!"); + return m->falseOrStop(); + } + } + iraVars->statsValueCounter[curStateValue]++; - return TM_RETURN_VALUE_OK; + return TM_RETURN_VALUE_OK; } //----------------------------------------------------------------------------- @@ -297,95 +271,85 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index) //----------------------------------------------------------------------------- bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars) { - // locals - unsigned int numKnotsInCurLayer; - StateAdress curState; // current state counter for loops - unsigned int curLayer = 0; // Counter variable - CountArrayVarType defValue = 0; // default counter array value - DWORD dwWritten; - DWORD dwRead; - LARGE_INTEGER fileSize; - HANDLE hFileCountArray = nullptr; // file handle for loading and saving the arrays in 'countArrays' - stringstream ssCountArrayPath; - stringstream ssCountArrayFilePath; - stringstream ssLayers; + // locals + unsigned int numKnotsInCurLayer; + StateAdress curState; // current state counter for loops + unsigned int curLayer = 0; // Counter variable + CountArrayVarType defValue = 0; // default counter array value + DWORD dwWritten; + DWORD dwRead; + LARGE_INTEGER fileSize; + HANDLE hFileCountArray = nullptr; // file handle for loading and saving the arrays in 'countArrays' + stringstream ssCountArrayPath; + stringstream ssCountArrayFilePath; + stringstream ssLayers; - // output & filenames - for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) - ssLayers << " " << retroVars.layersToCalculate[curLayer]; - ssCountArrayPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "countArray"; - ssCountArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "countArray\\countArray" << ssLayers.str() << ".dat"; - PRINT(2, this, " *** Prepare count arrays for layers " << ssLayers.str() << " ***" << endl); - curCalculationActionId = MM_ACTION_PREPARE_COUNT_ARRAY; + // output & filenames + for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) + ssLayers << " " << retroVars.layersToCalculate[curLayer]; + ssCountArrayPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "countArray"; + ssCountArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "countArray\\countArray" << ssLayers.str() << ".dat"; + PRINT(2, this, " *** Prepare count arrays for layers " << ssLayers.str() << " ***" << endl); + curCalculationActionId = MM_ACTION_PREPARE_COUNT_ARRAY; - // prepare count arrays - 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) - { - PRINT(0, this, "ERROR: Could not open File " << ssCountArrayFilePath.str() << "!"); - return falseOrStop(); - } + // prepare count arrays + 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) { + PRINT(0, this, "ERROR: Could not open File " << ssCountArrayFilePath.str() << "!"); + return falseOrStop(); + } - // allocate memory for count arrays - for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) - { - numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; - retroVars.countArrays[curLayer] = new CountArrayVarType[numKnotsInCurLayer]; - memoryUsed2 += numKnotsInCurLayer * sizeof(CountArrayVarType); - arrayInfos.addArray(retroVars.layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, numKnotsInCurLayer * sizeof(CountArrayVarType), 0); - } + // allocate memory for count arrays + for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) { + numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; + retroVars.countArrays[curLayer] = new CountArrayVarType[numKnotsInCurLayer]; + memoryUsed2 += numKnotsInCurLayer * sizeof(CountArrayVarType); + arrayInfos.addArray(retroVars.layersToCalculate[curLayer], ArrayInfo::arrayType_countArray, numKnotsInCurLayer * sizeof(CountArrayVarType), 0); + } - // load file if already existend - if (GetFileSizeEx(hFileCountArray, &fileSize) && fileSize.QuadPart == retroVars.numKnotsToCalc) - { - PRINT(2, this, " Load number of succedors from file: " << ssCountArrayFilePath.str().c_str()); + // load file if already existend + if (GetFileSizeEx(hFileCountArray, &fileSize) && fileSize.QuadPart == retroVars.numKnotsToCalc) { + PRINT(2, this, " Load number of succedors from file: " << ssCountArrayFilePath.str().c_str()); - for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) - { - numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; - if (!ReadFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwRead, nullptr)) - return falseOrStop(); - if (dwRead != numKnotsInCurLayer * sizeof(CountArrayVarType)) - return falseOrStop(); - } + for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) { + numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; + if (!ReadFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwRead, nullptr)) + return falseOrStop(); + if (dwRead != numKnotsInCurLayer * sizeof(CountArrayVarType)) + return falseOrStop(); + } - // else calculate number of succedding states - } - else - { + // else calculate number of succedding states + } else { - // Set default value 0 - for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) - { - numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; - for (curState.stateNumber = 0; curState.stateNumber < numKnotsInCurLayer; curState.stateNumber++) - { - retroVars.countArrays[curLayer][curState.stateNumber] = defValue; - } - } + // Set default value 0 + for (curLayer = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) { + numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; + for (curState.stateNumber = 0; curState.stateNumber < numKnotsInCurLayer; curState.stateNumber++) { + retroVars.countArrays[curLayer][curState.stateNumber] = defValue; + } + } - // calc values - if (!calcNumSuccedors(retroVars)) - { - CloseHandle(hFileCountArray); - return false; - } + // calc values + if (!calcNumSuccedors(retroVars)) { + CloseHandle(hFileCountArray); + return false; + } - // save to file - for (curLayer = 0, dwWritten = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) - { - numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; - if (!WriteFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwWritten, nullptr)) - return falseOrStop(); - if (dwWritten != numKnotsInCurLayer * sizeof(CountArrayVarType)) - return falseOrStop(); - } - PRINT(2, this, " Count array saved to file: " << ssCountArrayFilePath.str()); - } + // save to file + for (curLayer = 0, dwWritten = 0; curLayer < retroVars.layersToCalculate.size(); curLayer++) { + numKnotsInCurLayer = layerStats[retroVars.layersToCalculate[curLayer]].knotsInLayer; + if (!WriteFile(hFileCountArray, retroVars.countArrays[curLayer], numKnotsInCurLayer * sizeof(CountArrayVarType), &dwWritten, nullptr)) + return falseOrStop(); + if (dwWritten != numKnotsInCurLayer * sizeof(CountArrayVarType)) + return falseOrStop(); + } + PRINT(2, this, " Count array saved to file: " << ssCountArrayFilePath.str()); + } - // finish - CloseHandle(hFileCountArray); - return true; + // finish + CloseHandle(hFileCountArray); + return true; } //----------------------------------------------------------------------------- @@ -394,103 +358,96 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars) //----------------------------------------------------------------------------- bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars) { - // locals - unsigned int curLayerId; // current processed layer within 'layersToCalculate' - unsigned int layerNumber; // layer number of the current process layer - StateAdress curState; // current state counter for loops - StateAdress succState; // current succeding state counter for loops - vector succCalculated(skvfHeader.numLayers, false); // + // locals + unsigned int curLayerId; // current processed layer within 'layersToCalculate' + unsigned int layerNumber; // layer number of the current process layer + StateAdress curState; // current state counter for loops + StateAdress succState; // current succeding state counter for loops + vector succCalculated(skvfHeader.numLayers, false); // - // process each layer - for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) - { + // process each layer + for (curLayerId = 0; curLayerId < retroVars.layersToCalculate.size(); curLayerId++) { - // set current processed layer number - layerNumber = retroVars.layersToCalculate[curLayerId]; - PRINT(0, this, " *** Calculate number of succeding states for each state of layer " << layerNumber << " ***"); + // set current processed layer number + layerNumber = retroVars.layersToCalculate[curLayerId]; + PRINT(0, this, " *** Calculate number of succeding states for each state of layer " << layerNumber << " ***"); - // process layer ... - if (!succCalculated[layerNumber]) - { + // process layer ... + if (!succCalculated[layerNumber]) { - // prepare parameters for multithreading - succCalculated[layerNumber] = true; - numStatesProcessed = 0; - ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, layerNumber)); + // prepare parameters for multithreading + succCalculated[layerNumber] = true; + numStatesProcessed = 0; + ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, layerNumber)); - // process each state in the current layer - switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // process each state in the current layer + switch (threadManager.executeParallelLoop(addNumSuccedorsThreadProc, tva.getPointerToArray(), tva.getSizeOfArray(), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // reduce and delete thread specific data - tva.reduce(); - if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) - return falseOrStop(); + // reduce and delete thread specific data + tva.reduce(); + if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) + return falseOrStop(); - // don't calc layers twice - } - else - { - return falseOrStop(); - } + // don't calc layers twice + } else { + return falseOrStop(); + } - // ... and process succeding layers - for (curState.layerNumber = 0; curState.layerNumber < layerStats[layerNumber].numSuccLayers; curState.layerNumber++) - { + // ... and process succeding layers + for (curState.layerNumber = 0; curState.layerNumber < layerStats[layerNumber].numSuccLayers; curState.layerNumber++) { - // get current pred. layer - succState.layerNumber = layerStats[layerNumber].succLayers[curState.layerNumber]; + // get current pred. layer + succState.layerNumber = layerStats[layerNumber].succLayers[curState.layerNumber]; - // don't add layers twice - if (succCalculated[succState.layerNumber]) - continue; - else - succCalculated[succState.layerNumber] = true; + // don't add layers twice + if (succCalculated[succState.layerNumber]) + continue; + else + succCalculated[succState.layerNumber] = true; - // don't process layers without states - if (!layerStats[succState.layerNumber].knotsInLayer) - continue; + // don't process layers without states + if (!layerStats[succState.layerNumber].knotsInLayer) + continue; - // check all states of pred. layer - PRINT(2, this, " - Do the same for the succeding layer " << (int)succState.layerNumber); + // check all states of pred. layer + PRINT(2, this, " - Do the same for the succeding layer " << (int)succState.layerNumber); - // prepare parameters for multithreading - numStatesProcessed = 0; - ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, succState.layerNumber)); + // prepare parameters for multithreading + numStatesProcessed = 0; + ThreadManager::ThreadVarsArray tva(threadManager.getNumThreads(), AddNumSuccedorsVars(this, &retroVars, succState.layerNumber)); - // 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)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // 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)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // reduce and delete thread specific data - tva.reduce(); - if (numStatesProcessed < layerStats[succState.layerNumber].knotsInLayer) - return falseOrStop(); - } - } + // reduce and delete thread specific data + tva.reduce(); + if (numStatesProcessed < layerStats[succState.layerNumber].knotsInLayer) + return falseOrStop(); + } + } - // everything fine - return true; + // everything fine + return true; } //----------------------------------------------------------------------------- @@ -499,96 +456,87 @@ bool MiniMax::calcNumSuccedors(retroAnalysisGlobalVars &retroVars) //----------------------------------------------------------------------------- DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index) { - // locals - AddNumSuccedorsVars *ansVars = (AddNumSuccedorsVars *)pParameter; - MiniMax *m = ansVars->pMiniMax; - unsigned int numLayersToCalculate = (unsigned int)ansVars->retroVars->layersToCalculate.size(); - unsigned int curLayerId; // current processed layer within 'layersToCalculate' - unsigned int amountOfPred; - unsigned int curPred; - CountArrayVarType countValue; - StateAdress predState; - StateAdress curState; - TwoBit curStateValue; - PlyInfoVarType numPlies; // number of plies of the current considered succeding state - bool cuStateAddedToProcessQueue = false; + // locals + AddNumSuccedorsVars *ansVars = (AddNumSuccedorsVars *)pParameter; + MiniMax *m = ansVars->pMiniMax; + unsigned int numLayersToCalculate = (unsigned int)ansVars->retroVars->layersToCalculate.size(); + unsigned int curLayerId; // current processed layer within 'layersToCalculate' + unsigned int amountOfPred; + unsigned int curPred; + CountArrayVarType countValue; + StateAdress predState; + StateAdress curState; + TwoBit curStateValue; + PlyInfoVarType numPlies; // number of plies of the current considered succeding state + bool cuStateAddedToProcessQueue = false; - curState.layerNumber = ansVars->layerNumber; - curState.stateNumber = (StateNumberVarType)index; + curState.layerNumber = ansVars->layerNumber; + curState.stateNumber = (StateNumberVarType)index; - // print status - ansVars->statesProcessed++; - if (ansVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(2, m, " Already processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); - } + // print status + ansVars->statesProcessed++; + if (ansVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_STATES; + PRINT(2, m, " Already processed " << m->numStatesProcessed << " of " << m->layerStats[curState.layerNumber].knotsInLayer << " states"); + } - // invalid state ? - m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - if (curStateValue == SKV_VALUE_INVALID) - return TM_RETURN_VALUE_OK; + // invalid state ? + m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + if (curStateValue == SKV_VALUE_INVALID) + return TM_RETURN_VALUE_OK; - // set current selected situation - if (!m->setSituation(ansVars->curThreadNo, curState.layerNumber, curState.stateNumber)) - { - PRINT(0, m, "ERROR: setSituation() returned false!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } + // set current selected situation + if (!m->setSituation(ansVars->curThreadNo, curState.layerNumber, curState.stateNumber)) { + PRINT(0, m, "ERROR: setSituation() returned false!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } - // get list with statenumbers of predecessors - m->getPredecessors(ansVars->curThreadNo, &amountOfPred, ansVars->predVars); + // get list with statenumbers of predecessors + m->getPredecessors(ansVars->curThreadNo, &amountOfPred, ansVars->predVars); - // iteration - for (curPred = 0; curPred < amountOfPred; curPred++) - { + // iteration + for (curPred = 0; curPred < amountOfPred; curPred++) { - // current predecessor - predState.layerNumber = ansVars->predVars[curPred].predLayerNumbers; - predState.stateNumber = ansVars->predVars[curPred].predStateNumbers; + // current predecessor + predState.layerNumber = ansVars->predVars[curPred].predLayerNumbers; + predState.stateNumber = ansVars->predVars[curPred].predStateNumbers; - // don't calculate states from layers above yet - for (curLayerId = 0; curLayerId < numLayersToCalculate; curLayerId++) - { - if (ansVars->retroVars->layersToCalculate[curLayerId] == predState.layerNumber) - break; - } - if (curLayerId == numLayersToCalculate) - continue; + // don't calculate states from layers above yet + for (curLayerId = 0; curLayerId < numLayersToCalculate; curLayerId++) { + if (ansVars->retroVars->layersToCalculate[curLayerId] == predState.layerNumber) + break; + } + if (curLayerId == numLayersToCalculate) + continue; - // put in list (with states to be processed) if state is final - if (!cuStateAddedToProcessQueue && (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST)) - { - m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPlies); - m->addStateToProcessQueue(*ansVars->retroVars, ansVars->retroVars->thread[ansVars->curThreadNo], numPlies, &curState); - cuStateAddedToProcessQueue = true; - } + // put in list (with states to be processed) if state is final + if (!cuStateAddedToProcessQueue && (curStateValue == SKV_VALUE_GAME_WON || curStateValue == SKV_VALUE_GAME_LOST)) { + m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPlies); + m->addStateToProcessQueue(*ansVars->retroVars, ansVars->retroVars->thread[ansVars->curThreadNo], numPlies, &curState); + cuStateAddedToProcessQueue = true; + } - // add this state as possible move - long *pCountValue = ((long *)ansVars->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 mask = 0x000000ff << numBitsToShift; - long curCountLong, newCountLong; + // add this state as possible move + long *pCountValue = ((long *)ansVars->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 mask = 0x000000ff << numBitsToShift; + long curCountLong, newCountLong; - do - { - curCountLong = *pCountValue; - countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); - if (countValue == 255) - { - PRINT(0, m, "ERROR: maximum value for Count[] reached!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } - else - { - countValue++; - newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); - } - } while (InterlockedCompareExchange(pCountValue, newCountLong, curCountLong) != curCountLong); - } + do { + curCountLong = *pCountValue; + countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); + if (countValue == 255) { + PRINT(0, m, "ERROR: maximum value for Count[] reached!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } else { + countValue++; + newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); + } + } while (InterlockedCompareExchange(pCountValue, newCountLong, curCountLong) != curCountLong); + } - // everything is fine - return TM_RETURN_VALUE_OK; + // everything is fine + return TM_RETURN_VALUE_OK; } //----------------------------------------------------------------------------- @@ -597,56 +545,51 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index) //----------------------------------------------------------------------------- bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars) { - // locals - StateAdress curState; // current state counter for loops - TwoBit curStateValue; // current state value - unsigned int curLayerId; // current processed layer within 'layersToCalculate' + // locals + StateAdress curState; // current state counter for loops + TwoBit curStateValue; // current state value + unsigned int curLayerId; // current processed layer within 'layersToCalculate' - PRINT(2, this, " *** Begin Iteration ***"); - numStatesProcessed = 0; - curCalculationActionId = MM_ACTION_PERFORM_RETRO_ANAL; + PRINT(2, this, " *** Begin Iteration ***"); + numStatesProcessed = 0; + curCalculationActionId = MM_ACTION_PERFORM_RETRO_ANAL; - // process each state in the current layer - switch (threadManager.executeInParallel(performRetroAnalysisThreadProc, (void **)&retroVars, 0)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); - return false; - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // process each state in the current layer + switch (threadManager.executeInParallel(performRetroAnalysisThreadProc, (void **)&retroVars, 0)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + PRINT(0, this, "\n****************************************\nMain thread: Execution cancelled by user!\n****************************************\n"); + return false; + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // if there are still states to process, than something went wrong - for (unsigned int curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) - { - if (retroVars.thread[curThreadNo].numStatesToProcess) - { - PRINT(0, this, "ERROR: There are still states to process after performing retro analysis!"); - return falseOrStop(); - } - } + // if there are still states to process, than something went wrong + for (unsigned int curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) { + if (retroVars.thread[curThreadNo].numStatesToProcess) { + PRINT(0, this, "ERROR: There are still states to process after performing retro analysis!"); + return falseOrStop(); + } + } - // copy drawn and invalid states to ply info - PRINT(2, this, " Copy drawn and invalid states to ply info database..."); - 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++) - { - readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - if (curStateValue == SKV_VALUE_GAME_DRAWN) - savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_DRAWN); - if (curStateValue == SKV_VALUE_INVALID) - savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_INVALID); - } - } - PRINT(1, this, " *** Iteration finished! ***"); + // copy drawn and invalid states to ply info + PRINT(2, this, " Copy drawn and invalid states to ply info database..."); + 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++) { + readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + if (curStateValue == SKV_VALUE_GAME_DRAWN) + savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_DRAWN); + if (curStateValue == SKV_VALUE_INVALID) + savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_INVALID); + } + } + PRINT(1, this, " *** Iteration finished! ***"); - // every thing ok - return true; + // every thing ok + return true; } //----------------------------------------------------------------------------- @@ -655,178 +598,154 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars) //----------------------------------------------------------------------------- DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter) { - // locals - retroAnalysisGlobalVars *retroVars = (retroAnalysisGlobalVars *)pParameter; - MiniMax *m = retroVars->pMiniMax; - unsigned int threadNo = m->threadManager.getThreadNumber(); - RetroAnalysisThreadVars *threadVars = &retroVars->thread[threadNo]; + // locals + retroAnalysisGlobalVars *retroVars = (retroAnalysisGlobalVars *)pParameter; + MiniMax *m = retroVars->pMiniMax; + unsigned int threadNo = m->threadManager.getThreadNumber(); + RetroAnalysisThreadVars *threadVars = &retroVars->thread[threadNo]; - TwoBit predStateValue; - unsigned int curLayerId; // current processed layer within 'layersToCalculate' - unsigned int amountOfPred; // total numbers of predecessors and current considered one - unsigned int curPred; - unsigned int threadCounter; - long long numStatesProcessed; - long long totalNumStatesToProcess; - PlyInfoVarType curNumPlies; - PlyInfoVarType numPliesTillCurState; - PlyInfoVarType numPliesTillPredState; - CountArrayVarType countValue; - StateAdress predState; - StateAdress curState; // current state counter for while-loop - TwoBit curStateValue; // current state value - RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; + TwoBit predStateValue; + unsigned int curLayerId; // current processed layer within 'layersToCalculate' + unsigned int amountOfPred; // total numbers of predecessors and current considered one + unsigned int curPred; + unsigned int threadCounter; + long long numStatesProcessed; + long long totalNumStatesToProcess; + PlyInfoVarType curNumPlies; + PlyInfoVarType numPliesTillCurState; + PlyInfoVarType numPliesTillPredState; + CountArrayVarType countValue; + StateAdress predState; + StateAdress curState; // current state counter for while-loop + TwoBit curStateValue; // current state value + 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 - if (threadVars->statesToProcess[curNumPlies] != nullptr) - { + // skip empty and uninitialized cyclic arrays + if (threadVars->statesToProcess[curNumPlies] != nullptr) { - if (threadNo == 0) - { - PRINT(0, m, " Current number of plies: " << (unsigned int)curNumPlies << "/" << threadVars->statesToProcess.size()); - for (threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) - { - PRINT(0, m, " States to process for thread " << threadCounter << ": " << retroVars->thread[threadCounter].numStatesToProcess); - } - } + if (threadNo == 0) { + PRINT(0, m, " Current number of plies: " << (unsigned int)curNumPlies << "/" << threadVars->statesToProcess.size()); + for (threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) { + 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? - if (m->threadManager.wasExecutionCancelled()) - { - PRINT(0, m, "\n****************************************\nSub-thread no. " << threadNo << ": Execution cancelled by user!\n****************************************\n"); - return TM_RETURN_VALUE_EXECUTION_CANCELLED; - } + // execution cancelled by user? + if (m->threadManager.wasExecutionCancelled()) { + PRINT(0, m, "\n****************************************\nSub-thread no. " << threadNo << ": Execution cancelled by user!\n****************************************\n"); + return TM_RETURN_VALUE_EXECUTION_CANCELLED; + } - // get value of current state - m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPliesTillCurState); + // get value of current state + m->readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + m->readPlyInfoFromDatabase(curState.layerNumber, curState.stateNumber, numPliesTillCurState); - if (numPliesTillCurState != curNumPlies) - { - PRINT(0, m, "ERROR: numPliesTillCurState != curNumPlies"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } + if (numPliesTillCurState != curNumPlies) { + PRINT(0, m, "ERROR: numPliesTillCurState != curNumPlies"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } - // console output - numStatesProcessed++; - threadVars->numStatesToProcess--; - if (numStatesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - for (totalNumStatesToProcess = 0, threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) - { - totalNumStatesToProcess += retroVars->thread[threadCounter].numStatesToProcess; - } - PRINT(2, m, " states already processed: " << m->numStatesProcessed << " \t states still in list: " << totalNumStatesToProcess); - } + // console output + numStatesProcessed++; + threadVars->numStatesToProcess--; + if (numStatesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_STATES; + for (totalNumStatesToProcess = 0, threadCounter = 0; threadCounter < m->threadManager.getNumThreads(); threadCounter++) { + totalNumStatesToProcess += retroVars->thread[threadCounter].numStatesToProcess; + } + PRINT(2, m, " states already processed: " << m->numStatesProcessed << " \t states still in list: " << totalNumStatesToProcess); + } - // set current selected situation - if (!m->setSituation(threadNo, curState.layerNumber, curState.stateNumber)) - { - PRINT(0, m, "ERROR: setSituation() returned false!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } + // set current selected situation + if (!m->setSituation(threadNo, curState.layerNumber, curState.stateNumber)) { + PRINT(0, m, "ERROR: setSituation() returned false!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } - // get list with statenumbers of predecessors - m->getPredecessors(threadNo, &amountOfPred, predVars); + // get list with statenumbers of predecessors + m->getPredecessors(threadNo, &amountOfPred, predVars); - // iteration - for (curPred = 0; curPred < amountOfPred; curPred++) - { + // iteration + for (curPred = 0; curPred < amountOfPred; curPred++) { - // current predecessor - predState.layerNumber = predVars[curPred].predLayerNumbers; - predState.stateNumber = predVars[curPred].predStateNumbers; + // current predecessor + predState.layerNumber = predVars[curPred].predLayerNumbers; + predState.stateNumber = predVars[curPred].predStateNumbers; - // don't calculate states from layers above yet - for (curLayerId = 0; curLayerId < retroVars->layersToCalculate.size(); curLayerId++) - { - if (retroVars->layersToCalculate[curLayerId] == predState.layerNumber) - break; - } - if (curLayerId == retroVars->layersToCalculate.size()) - continue; + // don't calculate states from layers above yet + for (curLayerId = 0; curLayerId < retroVars->layersToCalculate.size(); curLayerId++) { + if (retroVars->layersToCalculate[curLayerId] == predState.layerNumber) + break; + } + if (curLayerId == retroVars->layersToCalculate.size()) + continue; - // get value of predecessor - m->readKnotValueFromDatabase(predState.layerNumber, predState.stateNumber, predStateValue); + // get value of predecessor + m->readKnotValueFromDatabase(predState.layerNumber, predState.stateNumber, predStateValue); - // only drawn states are relevant here, since the other are already calculated - if (predStateValue == SKV_VALUE_GAME_DRAWN) - { + // only drawn states are relevant here, since the other are already calculated + if (predStateValue == SKV_VALUE_GAME_DRAWN) { - // 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]) - { - m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_WON); - m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); // (requirement: curNumPlies == numPliesTillCurState) - if (numPliesTillCurState + 1 < curNumPlies) - { - PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } - 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 - } - else - { - // reduce count value by one - 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 mask = 0x000000ff << numBitsToShift; - long curCountLong, newCountLong; + // 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]) { + m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_WON); + m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); // (requirement: curNumPlies == numPliesTillCurState) + if (numPliesTillCurState + 1 < curNumPlies) { + PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } + 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 + } else { + // reduce count value by one + 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 mask = 0x000000ff << numBitsToShift; + long curCountLong, newCountLong; - do - { - curCountLong = *pCountValue; - countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); - if (countValue > 0) - { - countValue--; - newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); - } - else - { - PRINT(0, m, "ERROR: Count is already zero!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } - } while (InterlockedCompareExchange(pCountValue, newCountLong, curCountLong) != curCountLong); + do { + curCountLong = *pCountValue; + countValue = (CountArrayVarType)((curCountLong & mask) >> numBitsToShift); + if (countValue > 0) { + countValue--; + newCountLong = (curCountLong & (~mask)) + (countValue << numBitsToShift); + } else { + PRINT(0, m, "ERROR: Count is already zero!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } + } while (InterlockedCompareExchange(pCountValue, newCountLong, curCountLong) != curCountLong); - // ply info (requirement: curNumPlies == numPliesTillCurState) - m->readPlyInfoFromDatabase(predState.layerNumber, predState.stateNumber, numPliesTillPredState); - if (numPliesTillPredState == PLYINFO_VALUE_UNCALCULATED || numPliesTillCurState + 1 > numPliesTillPredState) - { - m->savePlyInfoInDatabase(predState.layerNumber, predState.stateNumber, numPliesTillCurState + 1); - } + // ply info (requirement: curNumPlies == numPliesTillCurState) + m->readPlyInfoFromDatabase(predState.layerNumber, predState.stateNumber, numPliesTillPredState); + if (numPliesTillPredState == PLYINFO_VALUE_UNCALCULATED || numPliesTillCurState + 1 > numPliesTillPredState) { + 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) - if (countValue == 0) - { - m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_LOST); - if (numPliesTillCurState + 1 < curNumPlies) - { - PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; - } - m->addStateToProcessQueue(*retroVars, *threadVars, numPliesTillCurState + 1, &predState); - } - } - } - } - } - } + // when all successor are won states then this is a lost state (this should only be the case for one thread) + if (countValue == 0) { + m->saveKnotValueInDatabase(predState.layerNumber, predState.stateNumber, SKV_VALUE_GAME_LOST); + if (numPliesTillCurState + 1 < curNumPlies) { + PRINT(0, m, "ERROR: Current number of plies is bigger than numPliesTillCurState + 1!"); + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + } + m->addStateToProcessQueue(*retroVars, *threadVars, numPliesTillCurState + 1, &predState); + } + } + } + } + } + } - // there might be other threads still processing states with this ply number - m->threadManager.waitForOtherThreads(threadNo); - } + // there might be other threads still processing states with this ply number + m->threadManager.waitForOtherThreads(threadNo); + } - // every thing ok - return TM_RETURN_VALUE_OK; + // every thing ok + return TM_RETURN_VALUE_OK; } //----------------------------------------------------------------------------- @@ -835,34 +754,31 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter) //----------------------------------------------------------------------------- bool MiniMax::addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState) { - // resize vector if too small - if (plyNumber >= threadVars.statesToProcess.size()) - { - threadVars.statesToProcess.resize(max(plyNumber + 1, 10 * threadVars.statesToProcess.size()), nullptr); - PRINT(4, this, " statesToProcess resized to " << threadVars.statesToProcess.size()); - } + // resize vector if too small + if (plyNumber >= threadVars.statesToProcess.size()) { + threadVars.statesToProcess.resize(max(plyNumber + 1, 10 * threadVars.statesToProcess.size()), nullptr); + PRINT(4, this, " statesToProcess resized to " << threadVars.statesToProcess.size()); + } - // initialize cyclic array if necessary - if (threadVars.statesToProcess[plyNumber] == nullptr) - { - stringstream ssStatesToProcessFilePath; - stringstream ssStatesToProcessPath; - ssStatesToProcessPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "statesToProcess"; - CreateDirectoryA(ssStatesToProcessPath.str().c_str(), nullptr); - ssStatesToProcessFilePath.str(""); - ssStatesToProcessFilePath << ssStatesToProcessPath.str() << "\\statesToProcessWithPlyCounter=" << plyNumber << "andThread=" << threadVars.threadNo << ".dat"; - threadVars.statesToProcess[plyNumber] = new CyclicArray(BLOCK_SIZE_IN_CYCLIC_ARRAY * sizeof(StateAdress), (unsigned int)(retroVars.totalNumKnots / BLOCK_SIZE_IN_CYCLIC_ARRAY) + 1, ssStatesToProcessFilePath.str().c_str()); - PRINT(4, this, " Created cyclic array: " << ssStatesToProcessFilePath.str()); - } + // initialize cyclic array if necessary + if (threadVars.statesToProcess[plyNumber] == nullptr) { + stringstream ssStatesToProcessFilePath; + stringstream ssStatesToProcessPath; + ssStatesToProcessPath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "statesToProcess"; + CreateDirectoryA(ssStatesToProcessPath.str().c_str(), nullptr); + ssStatesToProcessFilePath.str(""); + ssStatesToProcessFilePath << ssStatesToProcessPath.str() << "\\statesToProcessWithPlyCounter=" << plyNumber << "andThread=" << threadVars.threadNo << ".dat"; + threadVars.statesToProcess[plyNumber] = new CyclicArray(BLOCK_SIZE_IN_CYCLIC_ARRAY * sizeof(StateAdress), (unsigned int)(retroVars.totalNumKnots / BLOCK_SIZE_IN_CYCLIC_ARRAY) + 1, ssStatesToProcessFilePath.str().c_str()); + PRINT(4, this, " Created cyclic array: " << ssStatesToProcessFilePath.str()); + } - // add state - if (!threadVars.statesToProcess[plyNumber]->addBytes(sizeof(StateAdress), (unsigned char *)pState)) - { - PRINT(0, this, "ERROR: Cyclic list to small! numStatesToProcess:" << threadVars.numStatesToProcess); - return falseOrStop(); - } + // add state + if (!threadVars.statesToProcess[plyNumber]->addBytes(sizeof(StateAdress), (unsigned char *)pState)) { + PRINT(0, this, "ERROR: Cyclic list to small! numStatesToProcess:" << threadVars.numStatesToProcess); + return falseOrStop(); + } - // everything was fine - threadVars.numStatesToProcess++; - return true; + // everything was fine + threadVars.numStatesToProcess++; + return true; } diff --git a/src/perfect/miniMax_retroAnalysis.h b/src/perfect/miniMax_retroAnalysis.h index d3bb60bb..8c0ce0f9 100644 --- a/src/perfect/miniMax_retroAnalysis.h +++ b/src/perfect/miniMax_retroAnalysis.h @@ -1,71 +1,71 @@ /*********************************************************************\ - strLib.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + strLib.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ struct RetroAnalysisQueueState { - StateNumberVarType stateNumber; // state stored in the retro analysis queue. the queue is a buffer containing states to be passed to 'RetroAnalysisThreadVars::statesToProcess' - PlyInfoVarType numPliesTillCurState; // ply number for the stored state + StateNumberVarType stateNumber; // state stored in the retro analysis queue. the queue is a buffer containing states to be passed to 'RetroAnalysisThreadVars::statesToProcess' + PlyInfoVarType numPliesTillCurState; // ply number for the stored state }; struct RetroAnalysisThreadVars // thread specific variables for each thread in the retro analysis { - vector statesToProcess; // vector-queue containing the states, whose short knot value are known for sure. they have to be processed. if processed the state will be removed from list. indexing: [threadNo][plyNumber] - vector> stateQueue; // Queue containing states, whose 'count value' shall be increased by one. Before writing 'count value' to 'count array' the writing positions are sorted for faster processing. - long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed - unsigned int threadNo; + vector statesToProcess; // vector-queue containing the states, whose short knot value are known for sure. they have to be processed. if processed the state will be removed from list. indexing: [threadNo][plyNumber] + vector> stateQueue; // Queue containing states, whose 'count value' shall be increased by one. Before writing 'count value' to 'count array' the writing positions are sorted for faster processing. + long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed + unsigned int threadNo; }; struct RetroAnalysisVars // constant during calculation { - vector countArrays; // One count array for each layer in 'layersToCalculate'. (For the nine men's morris game two layers have to considered at once.) - vector countArraysCompr; // '' but compressed - vector layerInitialized; // - vector layersToCalculate; // layers which shall be calculated - long long totalNumKnots; // total numbers of knots which have to be stored in memory - long long numKnotsToCalc; // number of knots of all layers to be calculated - vector thread; + vector countArrays; // One count array for each layer in 'layersToCalculate'. (For the nine men's morris game two layers have to considered at once.) + vector countArraysCompr; // '' but compressed + vector layerInitialized; // + vector layersToCalculate; // layers which shall be calculated + long long totalNumKnots; // total numbers of knots which have to be stored in memory + long long numKnotsToCalc; // number of knots of all layers to be calculated + vector thread; }; struct InitRetroAnalysisVars { - MiniMax *pMiniMax; - unsigned int curThreadNo; - unsigned int layerNumber; - LONGLONG statesProcessed; - unsigned int statsValueCounter[SKV_NUM_VALUES]; - BufferedFile *bufferedFile; - RetroAnalysisVars *retroVars; - bool initAlreadyDone; // true if the initialization information is already available in a file + MiniMax *pMiniMax; + unsigned int curThreadNo; + unsigned int layerNumber; + LONGLONG statesProcessed; + unsigned int statsValueCounter[SKV_NUM_VALUES]; + BufferedFile *bufferedFile; + RetroAnalysisVars *retroVars; + bool initAlreadyDone; // true if the initialization information is already available in a file }; struct addSuccLayersVars { - MiniMax *pMiniMax; - unsigned int curThreadNo; - unsigned int statsValueCounter[SKV_NUM_VALUES]; - unsigned int layerNumber; - RetroAnalysisVars *retroVars; + MiniMax *pMiniMax; + unsigned int curThreadNo; + unsigned int statsValueCounter[SKV_NUM_VALUES]; + unsigned int layerNumber; + RetroAnalysisVars *retroVars; }; struct RetroAnalysisPredVars { - unsigned int predStateNumbers; - unsigned int predLayerNumbers; - unsigned int predSymOperation; - bool playerToMoveChanged; + unsigned int predStateNumbers; + unsigned int predLayerNumbers; + unsigned int predSymOperation; + bool playerToMoveChanged; }; struct AddNumSuccedorsVars { - MiniMax *pMiniMax; - unsigned int curThreadNo; - unsigned int layerNumber; - LONGLONG statesProcessed; - RetroAnalysisVars *retroVars; - RetroAnalysisPredVars *predVars; + MiniMax *pMiniMax; + unsigned int curThreadNo; + unsigned int layerNumber; + LONGLONG statesProcessed; + RetroAnalysisVars *retroVars; + RetroAnalysisPredVars *predVars; }; \ No newline at end of file diff --git a/src/perfect/miniMax_statistics.cpp b/src/perfect/miniMax_statistics.cpp index 8f5545ad..c14e396d 100644 --- a/src/perfect/miniMax_statistics.cpp +++ b/src/perfect/miniMax_statistics.cpp @@ -1,9 +1,9 @@ /********************************************************************* - miniMax_statistics.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax_statistics.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMax.h" @@ -14,7 +14,7 @@ //----------------------------------------------------------------------------- unsigned int MiniMax::getNumThreads() { - return threadManager.getNumThreads(); + return threadManager.getNumThreads(); } //----------------------------------------------------------------------------- @@ -23,7 +23,7 @@ unsigned int MiniMax::getNumThreads() //----------------------------------------------------------------------------- bool MiniMax::anyFreshlyCalculatedLayer() { - return (lastCalculatedLayer.size() > 0); + return (lastCalculatedLayer.size() > 0); } //----------------------------------------------------------------------------- @@ -32,9 +32,9 @@ bool MiniMax::anyFreshlyCalculatedLayer() //----------------------------------------------------------------------------- unsigned int MiniMax::getLastCalculatedLayer() { - unsigned int tmp = lastCalculatedLayer.front(); - lastCalculatedLayer.pop_front(); - return tmp; + unsigned int tmp = lastCalculatedLayer.front(); + lastCalculatedLayer.pop_front(); + return tmp; } //----------------------------------------------------------------------------- @@ -43,8 +43,8 @@ unsigned int MiniMax::getLastCalculatedLayer() //----------------------------------------------------------------------------- bool MiniMax::isLayerInDatabase(unsigned int layerNum) { - if (layerStats == nullptr) return false; - return layerStats[layerNum].layerIsCompletedAndInFile; + if (layerStats == nullptr) return false; + return layerStats[layerNum].layerIsCompletedAndInFile; } //----------------------------------------------------------------------------- @@ -53,8 +53,8 @@ bool MiniMax::isLayerInDatabase(unsigned int layerNum) //----------------------------------------------------------------------------- long long MiniMax::getLayerSizeInBytes(unsigned int layerNum) { - if (plyInfos == nullptr || layerStats == nullptr) return 0; - return (long long)layerStats[layerNum].sizeInBytes + (long long)plyInfos[layerNum].sizeInBytes; + if (plyInfos == nullptr || layerStats == nullptr) return 0; + return (long long)layerStats[layerNum].sizeInBytes + (long long)plyInfos[layerNum].sizeInBytes; } //----------------------------------------------------------------------------- @@ -63,8 +63,8 @@ long long MiniMax::getLayerSizeInBytes(unsigned int layerNum) //----------------------------------------------------------------------------- MiniMax::StateNumberVarType MiniMax::getNumWonStates(unsigned int layerNum) { - if (layerStats == nullptr) return 0; - return layerStats[layerNum].numWonStates; + if (layerStats == nullptr) return 0; + return layerStats[layerNum].numWonStates; } //----------------------------------------------------------------------------- @@ -73,8 +73,8 @@ MiniMax::StateNumberVarType MiniMax::getNumWonStates(unsigned int layerNum) //----------------------------------------------------------------------------- MiniMax::StateNumberVarType MiniMax::getNumLostStates(unsigned int layerNum) { - if (layerStats == nullptr) return 0; - return layerStats[layerNum].numLostStates; + if (layerStats == nullptr) return 0; + return layerStats[layerNum].numLostStates; } //----------------------------------------------------------------------------- @@ -83,8 +83,8 @@ MiniMax::StateNumberVarType MiniMax::getNumLostStates(unsigned int layerNum) //----------------------------------------------------------------------------- MiniMax::StateNumberVarType MiniMax::getNumDrawnStates(unsigned int layerNum) { - if (layerStats == nullptr) return 0; - return layerStats[layerNum].numDrawnStates; + if (layerStats == nullptr) return 0; + return layerStats[layerNum].numDrawnStates; } //----------------------------------------------------------------------------- @@ -93,8 +93,8 @@ MiniMax::StateNumberVarType MiniMax::getNumDrawnStates(unsigned int layerNum) //----------------------------------------------------------------------------- MiniMax::StateNumberVarType MiniMax::getNumInvalidStates(unsigned int layerNum) { - if (layerStats == nullptr) return 0; - return layerStats[layerNum].numInvalidStates; + if (layerStats == nullptr) return 0; + return layerStats[layerNum].numInvalidStates; } //----------------------------------------------------------------------------- @@ -103,18 +103,18 @@ MiniMax::StateNumberVarType MiniMax::getNumInvalidStates(unsigned int layerNum) //----------------------------------------------------------------------------- void MiniMax::showMemoryStatus() { - MEMORYSTATUSEX memStatus; - memStatus.dwLength = sizeof(memStatus); - GlobalMemoryStatusEx(&memStatus); + MEMORYSTATUSEX memStatus; + memStatus.dwLength = sizeof(memStatus); + GlobalMemoryStatusEx(&memStatus); - cout << endl << "dwMemoryLoad : " << memStatus.dwMemoryLoad; - cout << endl << "ullAvailExtendedVirtual: " << memStatus.ullAvailExtendedVirtual; - cout << endl << "ullAvailPageFile : " << memStatus.ullAvailPageFile; - cout << endl << "ullAvailPhys : " << memStatus.ullAvailPhys; - cout << endl << "ullAvailVirtual : " << memStatus.ullAvailVirtual; - cout << endl << "ullTotalPageFile : " << memStatus.ullTotalPageFile; - cout << endl << "ullTotalPhys : " << memStatus.ullTotalPhys; - cout << endl << "ullTotalVirtual : " << memStatus.ullTotalVirtual; + cout << endl << "dwMemoryLoad : " << memStatus.dwMemoryLoad; + cout << endl << "ullAvailExtendedVirtual: " << memStatus.ullAvailExtendedVirtual; + cout << endl << "ullAvailPageFile : " << memStatus.ullAvailPageFile; + cout << endl << "ullAvailPhys : " << memStatus.ullAvailPhys; + cout << endl << "ullAvailVirtual : " << memStatus.ullAvailVirtual; + cout << endl << "ullTotalPageFile : " << memStatus.ullTotalPageFile; + cout << endl << "ullTotalPhys : " << memStatus.ullTotalPhys; + cout << endl << "ullTotalVirtual : " << memStatus.ullTotalVirtual; } //----------------------------------------------------------------------------- @@ -123,9 +123,9 @@ void MiniMax::showMemoryStatus() //----------------------------------------------------------------------------- void MiniMax::setOutputStream(ostream *theStream, void(*printFunc)(void *pUserData), void *pUserData) { - osPrint = theStream; - pDataForUserPrintFunc = pUserData; - userPrintFunc = printFunc; + osPrint = theStream; + pDataForUserPrintFunc = pUserData; + userPrintFunc = printFunc; } //----------------------------------------------------------------------------- @@ -134,31 +134,31 @@ void MiniMax::setOutputStream(ostream *theStream, void(*printFunc)(void *pUserDa //----------------------------------------------------------------------------- void MiniMax::showLayerStats(unsigned int layerNumber) { - // locals - StateAdress curState; - unsigned int statsValueCounter[] = { 0,0,0,0 }; - TwoBit curStateValue; + // locals + StateAdress curState; + unsigned int statsValueCounter[] = { 0,0,0,0 }; + TwoBit curStateValue; - // calc and show statistics - for (curState.layerNumber = layerNumber, curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) { + // calc and show statistics + for (curState.layerNumber = layerNumber, curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) { - // get state value - readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - statsValueCounter[curStateValue]++; - } + // get state value + readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + statsValueCounter[curStateValue]++; + } - layerStats[layerNumber].numWonStates = statsValueCounter[SKV_VALUE_GAME_WON]; - layerStats[layerNumber].numLostStates = statsValueCounter[SKV_VALUE_GAME_LOST]; - layerStats[layerNumber].numDrawnStates = statsValueCounter[SKV_VALUE_GAME_DRAWN]; - layerStats[layerNumber].numInvalidStates = statsValueCounter[SKV_VALUE_INVALID]; + layerStats[layerNumber].numWonStates = statsValueCounter[SKV_VALUE_GAME_WON]; + layerStats[layerNumber].numLostStates = statsValueCounter[SKV_VALUE_GAME_LOST]; + layerStats[layerNumber].numDrawnStates = statsValueCounter[SKV_VALUE_GAME_DRAWN]; + layerStats[layerNumber].numInvalidStates = statsValueCounter[SKV_VALUE_INVALID]; - PRINT(1, this, endl << "FINAL STATISTICS OF LAYER " << layerNumber); - PRINT(1, this, (getOutputInformation(layerNumber))); - PRINT(1, this, " number states: " << layerStats[curState.layerNumber].knotsInLayer); - PRINT(1, this, " won states: " << statsValueCounter[SKV_VALUE_GAME_WON]); - PRINT(1, this, " lost states: " << statsValueCounter[SKV_VALUE_GAME_LOST]); - PRINT(1, this, " draw states: " << statsValueCounter[SKV_VALUE_GAME_DRAWN]); - PRINT(1, this, " invalid states: " << statsValueCounter[SKV_VALUE_INVALID]); + PRINT(1, this, endl << "FINAL STATISTICS OF LAYER " << layerNumber); + PRINT(1, this, (getOutputInformation(layerNumber))); + PRINT(1, this, " number states: " << layerStats[curState.layerNumber].knotsInLayer); + PRINT(1, this, " won states: " << statsValueCounter[SKV_VALUE_GAME_WON]); + PRINT(1, this, " lost states: " << statsValueCounter[SKV_VALUE_GAME_LOST]); + PRINT(1, this, " draw states: " << statsValueCounter[SKV_VALUE_GAME_DRAWN]); + PRINT(1, this, " invalid states: " << statsValueCounter[SKV_VALUE_INVALID]); } //----------------------------------------------------------------------------- @@ -167,93 +167,93 @@ void MiniMax::showLayerStats(unsigned int layerNumber) //----------------------------------------------------------------------------- bool MiniMax::calcLayerStatistics(char *statisticsFileName) { - // locals - HANDLE statFile; - DWORD dwBytesWritten; - StateAdress curState; - unsigned int *statsValueCounter; - TwoBit curStateValue; - char line[10000]; - string text(""); + // locals + HANDLE statFile; + DWORD dwBytesWritten; + StateAdress curState; + unsigned int *statsValueCounter; + TwoBit curStateValue; + char line[10000]; + string text(""); - // database must be open - if (hFileShortKnotValues == nullptr) return false; + // database must be open + if (hFileShortKnotValues == nullptr) return false; - // Open statistics file - statFile = CreateFileA(statisticsFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + // Open statistics file + statFile = CreateFileA(statisticsFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - // opened file succesfully? - if (statFile == INVALID_HANDLE_VALUE) { - statFile = nullptr; - return false; - } + // opened file succesfully? + if (statFile == INVALID_HANDLE_VALUE) { + statFile = nullptr; + return false; + } - // headline - text += "layer number\t"; - text += "white stones\t"; - text += "black stones\t"; - text += "won states\t"; - text += "lost states\t"; - text += "draw states\t"; - text += "invalid states\t"; - text += "total num states\t"; - text += "num succeding layers\t"; - text += "partner layer\t"; - text += "size in bytes\t"; - text += "succLayers[0]\t"; - text += "succLayers[1]\n"; + // headline + text += "layer number\t"; + text += "white stones\t"; + text += "black stones\t"; + text += "won states\t"; + text += "lost states\t"; + text += "draw states\t"; + text += "invalid states\t"; + text += "total num states\t"; + text += "num succeding layers\t"; + text += "partner layer\t"; + text += "size in bytes\t"; + text += "succLayers[0]\t"; + text += "succLayers[1]\n"; - statsValueCounter = new unsigned int[4 * skvfHeader.numLayers]; - curCalculationActionId = MM_ACTION_CALC_LAYER_STATS; + statsValueCounter = new unsigned int[4 * skvfHeader.numLayers]; + curCalculationActionId = MM_ACTION_CALC_LAYER_STATS; - // calc and show statistics - for (layerInDatabase = false, curState.layerNumber = 0; curState.layerNumber < skvfHeader.numLayers; curState.layerNumber++) { + // calc and show statistics + for (layerInDatabase = false, curState.layerNumber = 0; curState.layerNumber < skvfHeader.numLayers; curState.layerNumber++) { - // status output - PRINT(0, this, "Calculating statistics of layer: " << (int)curState.layerNumber); + // status output + PRINT(0, this, "Calculating statistics of layer: " << (int)curState.layerNumber); - // zero counters - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_WON] = 0; - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_LOST] = 0; - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_DRAWN] = 0; - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_INVALID] = 0; + // zero counters + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_WON] = 0; + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_LOST] = 0; + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_DRAWN] = 0; + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_INVALID] = 0; - // only calc stats of completed layers - if (layerStats[curState.layerNumber].layerIsCompletedAndInFile) { + // only calc stats of completed layers + if (layerStats[curState.layerNumber].layerIsCompletedAndInFile) { - for (curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) { + for (curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) { - // get state value - readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); - statsValueCounter[4 * curState.layerNumber + curStateValue]++; - } + // get state value + readKnotValueFromDatabase(curState.layerNumber, curState.stateNumber, curStateValue); + statsValueCounter[4 * curState.layerNumber + curStateValue]++; + } - // free memory - unloadLayer(curState.layerNumber); - } + // free memory + unloadLayer(curState.layerNumber); + } - // add line - sprintf_s(line, "%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", - curState.layerNumber, - getOutputInformation(curState.layerNumber).c_str(), - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_WON], - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_LOST], - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_DRAWN], - statsValueCounter[4 * curState.layerNumber + SKV_VALUE_INVALID], - layerStats[curState.layerNumber].knotsInLayer, - layerStats[curState.layerNumber].numSuccLayers, - layerStats[curState.layerNumber].partnerLayer, - layerStats[curState.layerNumber].sizeInBytes, - layerStats[curState.layerNumber].succLayers[0], - layerStats[curState.layerNumber].succLayers[1]); - text += line; - } + // add line + sprintf_s(line, "%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + curState.layerNumber, + getOutputInformation(curState.layerNumber).c_str(), + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_WON], + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_LOST], + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_GAME_DRAWN], + statsValueCounter[4 * curState.layerNumber + SKV_VALUE_INVALID], + layerStats[curState.layerNumber].knotsInLayer, + layerStats[curState.layerNumber].numSuccLayers, + layerStats[curState.layerNumber].partnerLayer, + layerStats[curState.layerNumber].sizeInBytes, + layerStats[curState.layerNumber].succLayers[0], + layerStats[curState.layerNumber].succLayers[1]); + text += line; + } - // write to file and close it - WriteFile(statFile, text.c_str(), (DWORD)text.length(), &dwBytesWritten, nullptr); - CloseHandle(statFile); - SAFE_DELETE_ARRAY(statsValueCounter); - return true; + // write to file and close it + WriteFile(statFile, text.c_str(), (DWORD)text.length(), &dwBytesWritten, nullptr); + CloseHandle(statFile); + SAFE_DELETE_ARRAY(statsValueCounter); + return true; } //----------------------------------------------------------------------------- @@ -262,7 +262,7 @@ bool MiniMax::calcLayerStatistics(char *statisticsFileName) //----------------------------------------------------------------------------- bool MiniMax::anyArrawInfoToUpdate() { - return (arrayInfos.arrayInfosToBeUpdated.size() > 0); + return (arrayInfos.arrayInfosToBeUpdated.size() > 0); } //----------------------------------------------------------------------------- @@ -271,9 +271,9 @@ bool MiniMax::anyArrawInfoToUpdate() //----------------------------------------------------------------------------- MiniMax::ArrayInfoChange MiniMax::getArrayInfoForUpdate() { - MiniMax::ArrayInfoChange tmp = arrayInfos.arrayInfosToBeUpdated.front(); - arrayInfos.arrayInfosToBeUpdated.pop_front(); - return tmp; + MiniMax::ArrayInfoChange tmp = arrayInfos.arrayInfosToBeUpdated.front(); + arrayInfos.arrayInfosToBeUpdated.pop_front(); + return tmp; } //----------------------------------------------------------------------------- @@ -282,17 +282,17 @@ MiniMax::ArrayInfoChange MiniMax::getArrayInfoForUpdate() //----------------------------------------------------------------------------- LPWSTR MiniMax::getCurrentActionStr() { - switch (curCalculationActionId) { - case MM_ACTION_INIT_RETRO_ANAL: return L"initiating retro-analysis"; - case MM_ACTION_PREPARE_COUNT_ARRAY: return L"preparing count arrays"; - case MM_ACTION_PERFORM_RETRO_ANAL: return L"performing retro analysis"; - case MM_ACTION_PERFORM_ALPHA_BETA: return L"performing alpha-beta-algorithmn"; - case MM_ACTION_TESTING_LAYER: return L"testing calculated layer"; - case MM_ACTION_SAVING_LAYER_TO_FILE: return L"saving layer to file"; - case MM_ACTION_CALC_LAYER_STATS: return L"making layer statistics"; - case MM_ACTION_NONE: return L"none"; - default: return L"undefined"; - } + switch (curCalculationActionId) { + case MM_ACTION_INIT_RETRO_ANAL: return L"initiating retro-analysis"; + case MM_ACTION_PREPARE_COUNT_ARRAY: return L"preparing count arrays"; + case MM_ACTION_PERFORM_RETRO_ANAL: return L"performing retro analysis"; + case MM_ACTION_PERFORM_ALPHA_BETA: return L"performing alpha-beta-algorithmn"; + case MM_ACTION_TESTING_LAYER: return L"testing calculated layer"; + case MM_ACTION_SAVING_LAYER_TO_FILE: return L"saving layer to file"; + case MM_ACTION_CALC_LAYER_STATS: return L"making layer statistics"; + case MM_ACTION_NONE: return L"none"; + default: return L"undefined"; + } } //----------------------------------------------------------------------------- @@ -301,15 +301,15 @@ LPWSTR MiniMax::getCurrentActionStr() //----------------------------------------------------------------------------- void MiniMax::getCurrentCalculatedLayer(vector &layers) { - // when retro-analysis is used than two layers are calculated at the same time - if (shallRetroAnalysisBeUsed(curCalculatedLayer) && layerStats[curCalculatedLayer].partnerLayer != curCalculatedLayer) { - layers.resize(2); - layers[0] = curCalculatedLayer; - layers[1] = layerStats[curCalculatedLayer].partnerLayer; - } else { - layers.resize(1); - layers[0] = curCalculatedLayer; - } + // when retro-analysis is used than two layers are calculated at the same time + if (shallRetroAnalysisBeUsed(curCalculatedLayer) && layerStats[curCalculatedLayer].partnerLayer != curCalculatedLayer) { + layers.resize(2); + layers[0] = curCalculatedLayer; + layers[1] = layerStats[curCalculatedLayer].partnerLayer; + } else { + layers.resize(1); + layers[0] = curCalculatedLayer; + } } //----------------------------------------------------------------------------- @@ -319,30 +319,30 @@ void MiniMax::getCurrentCalculatedLayer(vector &layers) //----------------------------------------------------------------------------- void MiniMax::ArrayInfoContainer::addArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize) { - // create new info object and add to list - EnterCriticalSection(&c->csOsPrint); - ArrayInfo ais; - ais.belongsToLayer = layerNumber; - ais.compressedSizeInBytes = compressedSize; - ais.sizeInBytes = size; - ais.type = type; - ais.updateCounter = 0; - listArrays.push_back(ais); + // create new info object and add to list + EnterCriticalSection(&c->csOsPrint); + ArrayInfo ais; + ais.belongsToLayer = layerNumber; + ais.compressedSizeInBytes = compressedSize; + ais.sizeInBytes = size; + ais.type = type; + ais.updateCounter = 0; + listArrays.push_back(ais); - // notify cahnge - ArrayInfoChange aic; - aic.arrayInfo = &listArrays.back(); - aic.itemIndex = (unsigned int)listArrays.size() - 1; - arrayInfosToBeUpdated.push_back(aic); + // notify cahnge + ArrayInfoChange aic; + aic.arrayInfo = &listArrays.back(); + aic.itemIndex = (unsigned int)listArrays.size() - 1; + arrayInfosToBeUpdated.push_back(aic); - // save pointer of info in vector for direct access - vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type] = (--listArrays.end()); + // save pointer of info in vector for direct access + vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type] = (--listArrays.end()); - // update GUI - if (c->userPrintFunc != nullptr) { - c->userPrintFunc(c->pDataForUserPrintFunc); - } - LeaveCriticalSection(&c->csOsPrint); + // update GUI + if (c->userPrintFunc != nullptr) { + c->userPrintFunc(c->pDataForUserPrintFunc); + } + LeaveCriticalSection(&c->csOsPrint); } //----------------------------------------------------------------------------- @@ -351,34 +351,34 @@ void MiniMax::ArrayInfoContainer::addArray(unsigned int layerNumber, unsigned in //----------------------------------------------------------------------------- void MiniMax::ArrayInfoContainer::removeArray(unsigned int layerNumber, unsigned int type, long long size, long long compressedSize) { - // find info object in list - EnterCriticalSection(&c->csOsPrint); + // find info object in list + EnterCriticalSection(&c->csOsPrint); - if (vectorArrays.size() > layerNumber * ArrayInfo::numArrayTypes + type) { - list::iterator itr = vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type]; - if (itr != listArrays.end()) { + if (vectorArrays.size() > layerNumber * ArrayInfo::numArrayTypes + type) { + list::iterator itr = vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type]; + if (itr != listArrays.end()) { - // does sizes fit? - if (itr->belongsToLayer != layerNumber || itr->type != type || itr->sizeInBytes != size || itr->compressedSizeInBytes != compressedSize) { - c->falseOrStop(); - } + // does sizes fit? + if (itr->belongsToLayer != layerNumber || itr->type != type || itr->sizeInBytes != size || itr->compressedSizeInBytes != compressedSize) { + c->falseOrStop(); + } - // notify cahnge - ArrayInfoChange aic; - aic.arrayInfo = nullptr; - aic.itemIndex = (unsigned int)std::distance(listArrays.begin(), itr); - arrayInfosToBeUpdated.push_back(aic); + // notify cahnge + ArrayInfoChange aic; + aic.arrayInfo = nullptr; + aic.itemIndex = (unsigned int)std::distance(listArrays.begin(), itr); + arrayInfosToBeUpdated.push_back(aic); - // delete tem from list - listArrays.erase(itr); - } - } + // delete tem from list + listArrays.erase(itr); + } + } - // update GUI - if (c->userPrintFunc != nullptr) { - c->userPrintFunc(c->pDataForUserPrintFunc); - } - LeaveCriticalSection(&c->csOsPrint); + // update GUI + if (c->userPrintFunc != nullptr) { + c->userPrintFunc(c->pDataForUserPrintFunc); + } + LeaveCriticalSection(&c->csOsPrint); } //----------------------------------------------------------------------------- @@ -387,24 +387,24 @@ void MiniMax::ArrayInfoContainer::removeArray(unsigned int layerNumber, unsigned //----------------------------------------------------------------------------- void MiniMax::ArrayInfoContainer::updateArray(unsigned int layerNumber, unsigned int type) { - // find info object in list - list::iterator itr = vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type]; + // find info object in list + list::iterator itr = vectorArrays[layerNumber * ArrayInfo::numArrayTypes + type]; - itr->updateCounter++; - if (itr->updateCounter > ArrayInfo::updateCounterThreshold) { + itr->updateCounter++; + if (itr->updateCounter > ArrayInfo::updateCounterThreshold) { - // notify cahnge - EnterCriticalSection(&c->csOsPrint); - ArrayInfoChange aic; - aic.arrayInfo = &(*itr); - aic.itemIndex = (unsigned int)std::distance(listArrays.begin(), itr); - arrayInfosToBeUpdated.push_back(aic); + // notify cahnge + EnterCriticalSection(&c->csOsPrint); + ArrayInfoChange aic; + aic.arrayInfo = &(*itr); + aic.itemIndex = (unsigned int)std::distance(listArrays.begin(), itr); + arrayInfosToBeUpdated.push_back(aic); - // update GUI - if (c->userPrintFunc != nullptr) { - c->userPrintFunc(c->pDataForUserPrintFunc); - } - itr->updateCounter = 0; - LeaveCriticalSection(&c->csOsPrint); - } + // update GUI + if (c->userPrintFunc != nullptr) { + c->userPrintFunc(c->pDataForUserPrintFunc); + } + itr->updateCounter = 0; + LeaveCriticalSection(&c->csOsPrint); + } } \ No newline at end of file diff --git a/src/perfect/miniMax_test.cpp b/src/perfect/miniMax_test.cpp index 82bf9466..d778354a 100644 --- a/src/perfect/miniMax_test.cpp +++ b/src/perfect/miniMax_test.cpp @@ -1,9 +1,9 @@ /********************************************************************* - miniMax_test.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + miniMax_test.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "miniMax.h" @@ -14,82 +14,72 @@ //----------------------------------------------------------------------------- bool MiniMax::testLayer(unsigned int layerNumber) { - // Locals - unsigned int curThreadNo; - unsigned int returnValue; + // Locals + unsigned int curThreadNo; + unsigned int returnValue; - // database open? - if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) - { - PRINT(0, this, "ERROR: Database file not open!"); - return falseOrStop(); - } + // database open? + if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) { + PRINT(0, this, "ERROR: Database file not open!"); + return falseOrStop(); + } - // output - PRINT(1, this, endl << "*** Test each state in layer: " << layerNumber << " ***"); - PRINT(1, this, (getOutputInformation(layerNumber))); + // output + PRINT(1, this, endl << "*** Test each state in layer: " << layerNumber << " ***"); + PRINT(1, this, (getOutputInformation(layerNumber))); - // prepare parameters for multithreading - skvfHeader.completed = false; - layerInDatabase = false; - numStatesProcessed = 0; - curCalculatedLayer = layerNumber; - curCalculationActionId = MM_ACTION_TESTING_LAYER; - TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; - for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) - { - tlVars[curThreadNo].curThreadNo = curThreadNo; - tlVars[curThreadNo].pMiniMax = this; - tlVars[curThreadNo].layerNumber = layerNumber; - tlVars[curThreadNo].statesProcessed = 0; - tlVars[curThreadNo].subValueInDatabase = new TwoBit[maxNumBranches]; - tlVars[curThreadNo].subPlyInfos = new PlyInfoVarType[maxNumBranches]; - tlVars[curThreadNo].hasCurPlayerChanged = new bool[maxNumBranches]; - } + // prepare parameters for multithreading + skvfHeader.completed = false; + layerInDatabase = false; + numStatesProcessed = 0; + curCalculatedLayer = layerNumber; + curCalculationActionId = MM_ACTION_TESTING_LAYER; + TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; + for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) { + tlVars[curThreadNo].curThreadNo = curThreadNo; + tlVars[curThreadNo].pMiniMax = this; + tlVars[curThreadNo].layerNumber = layerNumber; + tlVars[curThreadNo].statesProcessed = 0; + tlVars[curThreadNo].subValueInDatabase = new TwoBit[maxNumBranches]; + tlVars[curThreadNo].subPlyInfos = new PlyInfoVarType[maxNumBranches]; + tlVars[curThreadNo].hasCurPlayerChanged = new bool[maxNumBranches]; + } - // process each state in the current layer - returnValue = threadManager.executeParallelLoop(testLayerThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); - switch (returnValue) - { - case TM_RETURN_VALUE_OK: - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - // reduce and delete thread specific data - for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) - { - numStatesProcessed += tlVars[curThreadNo].statesProcessed; - SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); - SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); - SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); - } - SAFE_DELETE_ARRAY(tlVars); - if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) - { - PRINT(0, this, "Main thread: Execution cancelled by user"); - return false; // ... better would be to return a cancel-specific value - } - else - { - break; - } - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // process each state in the current layer + returnValue = threadManager.executeParallelLoop(testLayerThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); + switch (returnValue) { + case TM_RETURN_VALUE_OK: + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + // reduce and delete thread specific data + for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) { + numStatesProcessed += tlVars[curThreadNo].statesProcessed; + SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); + SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); + SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); + } + SAFE_DELETE_ARRAY(tlVars); + if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) { + PRINT(0, this, "Main thread: Execution cancelled by user"); + return false; // ... better would be to return a cancel-specific value + } else { + break; + } + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // layer is not ok - if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) - { - PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); - return falseOrStop(); - // layer is ok - } - else - { - PRINT(1, this, " TEST PASSED !" << endl - << endl); - return true; - } + // layer is not ok + if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) { + PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); + return falseOrStop(); + // layer is ok + } else { + PRINT(1, this, " TEST PASSED !" << endl + << endl); + return true; + } } //----------------------------------------------------------------------------- @@ -98,268 +88,229 @@ bool MiniMax::testLayer(unsigned int layerNumber) //----------------------------------------------------------------------------- DWORD MiniMax::testLayerThreadProc(void *pParameter, int index) { - // locals - TestLayersVars *tlVars = (TestLayersVars *)pParameter; - MiniMax *m = tlVars->pMiniMax; - unsigned int layerNumber = tlVars->layerNumber; - unsigned int stateNumber = index; - unsigned int threadNo = tlVars->curThreadNo; - TwoBit *subValueInDatabase = tlVars->subValueInDatabase; - PlyInfoVarType *subPlyInfos = tlVars->subPlyInfos; - bool *hasCurPlayerChanged = tlVars->hasCurPlayerChanged; - TwoBit shortValueInDatabase; - PlyInfoVarType numPliesTillCurState; - TwoBit shortValueInGame; - float floatValueInGame; - PlyInfoVarType min, max; - unsigned int numPossibilities; - unsigned int i, j; - unsigned int tmpStateNumber, tmpLayerNumber; - unsigned int *idPossibility; - void *pPossibilities; - void *pBackup; - bool isOpponentLevel; - bool invalidLayerOrStateNumber; - bool layerInDatabaseAndCompleted; + // locals + TestLayersVars *tlVars = (TestLayersVars *)pParameter; + MiniMax *m = tlVars->pMiniMax; + unsigned int layerNumber = tlVars->layerNumber; + unsigned int stateNumber = index; + unsigned int threadNo = tlVars->curThreadNo; + TwoBit *subValueInDatabase = tlVars->subValueInDatabase; + PlyInfoVarType *subPlyInfos = tlVars->subPlyInfos; + bool *hasCurPlayerChanged = tlVars->hasCurPlayerChanged; + TwoBit shortValueInDatabase; + PlyInfoVarType numPliesTillCurState; + TwoBit shortValueInGame; + float floatValueInGame; + PlyInfoVarType min, max; + unsigned int numPossibilities; + unsigned int i, j; + unsigned int tmpStateNumber, tmpLayerNumber; + unsigned int *idPossibility; + void *pPossibilities; + void *pBackup; + bool isOpponentLevel; + bool invalidLayerOrStateNumber; + bool layerInDatabaseAndCompleted; - // output - tlVars->statesProcessed++; - if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[layerNumber].knotsInLayer << " tested"); - } + // output + tlVars->statesProcessed++; + if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_STATES; + PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[layerNumber].knotsInLayer << " tested"); + } - // situation already existend in database ? - m->readKnotValueFromDatabase(layerNumber, stateNumber, shortValueInDatabase); - m->readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); + // situation already existend in database ? + m->readKnotValueFromDatabase(layerNumber, stateNumber, shortValueInDatabase); + m->readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); - // prepare the situation - if (!m->setSituation(threadNo, layerNumber, stateNumber)) - { + // prepare the situation + if (!m->setSituation(threadNo, layerNumber, stateNumber)) { - // when situation cannot be constructed then state must be marked as invalid in database - 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."); - goto errorInDatabase; - } - else - { - return TM_RETURN_VALUE_OK; - } - } + // when situation cannot be constructed then state must be marked as invalid in database + 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."); + goto errorInDatabase; + } else { + return TM_RETURN_VALUE_OK; + } + } - // debug information - if (m->verbosity > 5) - { - PRINT(5, m, "layer: " << layerNumber << " state: " << stateNumber); - m->printBoard(threadNo, shortValueInDatabase); - } + // debug information + if (m->verbosity > 5) { + PRINT(5, m, "layer: " << layerNumber << " state: " << stateNumber); + m->printBoard(threadNo, shortValueInDatabase); + } - // get number of possiblities - m->setOpponentLevel(threadNo, false); - idPossibility = m->getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + // get number of possiblities + m->setOpponentLevel(threadNo, false); + idPossibility = m->getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - // unable to move - if (numPossibilities == 0) - { + // unable to move + if (numPossibilities == 0) { - // get ingame value - m->getValueOfSituation(threadNo, floatValueInGame, shortValueInGame); + // get ingame value + m->getValueOfSituation(threadNo, floatValueInGame, shortValueInGame); - // compare database with game - 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."); - goto errorInDatabase; - } - 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."); - goto errorInDatabase; - } - } - else - { + // compare database with game + 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."); + goto errorInDatabase; + } + 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."); + goto errorInDatabase; + } + } else { - // check each possible move - for (i = 0; i < numPossibilities; i++) - { + // check each possible move + for (i = 0; i < numPossibilities; i++) { - // move - m->move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); + // move + m->move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); - // get database value - m->readKnotValueFromDatabase(threadNo, tmpLayerNumber, tmpStateNumber, subValueInDatabase[i], invalidLayerOrStateNumber, layerInDatabaseAndCompleted); - m->readPlyInfoFromDatabase(tmpLayerNumber, tmpStateNumber, subPlyInfos[i]); - hasCurPlayerChanged[i] = (m->getOpponentLevel(threadNo) == true); + // get database value + m->readKnotValueFromDatabase(threadNo, tmpLayerNumber, tmpStateNumber, subValueInDatabase[i], invalidLayerOrStateNumber, layerInDatabaseAndCompleted); + m->readPlyInfoFromDatabase(tmpLayerNumber, tmpStateNumber, subPlyInfos[i]); + hasCurPlayerChanged[i] = (m->getOpponentLevel(threadNo) == true); - // debug information - if (m->verbosity > 5) - { - PRINT(5, m, "layer: " << tmpLayerNumber << " state: " << tmpStateNumber << " value: " << (int)subValueInDatabase[i]); - m->printBoard(threadNo, subValueInDatabase[i]); - } + // debug information + if (m->verbosity > 5) { + PRINT(5, m, "layer: " << tmpLayerNumber << " state: " << tmpStateNumber << " value: " << (int)subValueInDatabase[i]); + m->printBoard(threadNo, subValueInDatabase[i]); + } - // if layer or state number is invalid then value of testes state must be 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."); - goto errorInDatabase; - } - // BUG: Does not work because, layer 101 is calculated before 105, although removing a stone does need this jump. - // if (!layerInDatabaseAndCompleted) { PRINT(0,m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Succeding state " << tmpStateNumber << " in an uncalculated layer " << tmpLayerNumber << "! Calc layer first!"); goto errorInDatabase; } + // if layer or state number is invalid then value of testes state must be 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."); + goto errorInDatabase; + } + // BUG: Does not work because, layer 101 is calculated before 105, although removing a stone does need this jump. + // if (!layerInDatabaseAndCompleted) { PRINT(0,m, "ERROR: DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Succeding state " << tmpStateNumber << " in an uncalculated layer " << tmpLayerNumber << "! Calc layer first!"); goto errorInDatabase; } - // undo move - m->undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); - } + // undo move + m->undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); + } - // value possible? - switch (shortValueInDatabase) - { - case SKV_VALUE_GAME_LOST: + // value possible? + switch (shortValueInDatabase) { + case SKV_VALUE_GAME_LOST: - // all possible moves must be lost for the current player or won for the opponent - for (i = 0; i < numPossibilities; i++) - { - 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"); - goto errorInDatabase; - } - } - // not all options can be invalid - for (j = 0, i = 0; i < numPossibilities; i++) - { - if (subValueInDatabase[i] == SKV_VALUE_INVALID) - { - j++; - } - } - if (j == numPossibilities) - { - PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ". Not all options can be invalid"); - } - // ply info must be max(subPlyInfos[]+1) - max = 0; - for (i = 0; i < numPossibilities; i++) - { - if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST)) - { - if (subPlyInfos[i] + 1 > max) - { - max = subPlyInfos[i] + 1; - } - } - } - 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."); - goto errorInDatabase; - } - if (numPliesTillCurState != max) - { - PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not maximal for LOST state."); - goto errorInDatabase; - } - break; + // all possible moves must be lost for the current player or won for the opponent + for (i = 0; i < numPossibilities; i++) { + 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"); + goto errorInDatabase; + } + } + // not all options can be invalid + for (j = 0, i = 0; i < numPossibilities; i++) { + if (subValueInDatabase[i] == SKV_VALUE_INVALID) { + j++; + } + } + if (j == numPossibilities) { + PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ". Not all options can be invalid"); + } + // ply info must be max(subPlyInfos[]+1) + max = 0; + for (i = 0; i < numPossibilities; i++) { + if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_WON : SKV_VALUE_GAME_LOST)) { + if (subPlyInfos[i] + 1 > max) { + max = subPlyInfos[i] + 1; + } + } + } + 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."); + goto errorInDatabase; + } + if (numPliesTillCurState != max) { + PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not maximal for LOST state."); + goto errorInDatabase; + } + break; - 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 - 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] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) - 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."); - goto errorInDatabase; - } + // at least one possible move must be lost for the opponent or won for the current player + 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] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) + 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."); + goto errorInDatabase; + } - // ply info must be min(subPlyInfos[]+1) - min = PLYINFO_VALUE_DRAWN; - for (i = 0; i < numPossibilities; i++) - { - if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) - { - if (subPlyInfos[i] + 1 < min) - { - min = subPlyInfos[i] + 1; - } - } - } - 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."); - goto errorInDatabase; - } - if (numPliesTillCurState != min) - { - PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not minimal for WON state."); - goto errorInDatabase; - } - break; + // ply info must be min(subPlyInfos[]+1) + min = PLYINFO_VALUE_DRAWN; + for (i = 0; i < numPossibilities; i++) { + if (subValueInDatabase[i] == ((hasCurPlayerChanged[i]) ? SKV_VALUE_GAME_LOST : SKV_VALUE_GAME_WON)) { + if (subPlyInfos[i] + 1 < min) { + min = subPlyInfos[i] + 1; + } + } + } + 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."); + goto errorInDatabase; + } + if (numPliesTillCurState != min) { + PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": Number of needed plies is not minimal for WON state."); + goto errorInDatabase; + } + break; - 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 - 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] != ((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."); - goto errorInDatabase; - } - if (subValueInDatabase[i] == SKV_VALUE_GAME_DRAWN) - j = 1; - } + // all possible moves must be won for the opponent, lost for the current player or drawn + 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] != ((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."); + goto errorInDatabase; + } + if (subValueInDatabase[i] == SKV_VALUE_GAME_DRAWN) + j = 1; + } - // at least one succeding state must be drawn - if (j == 0) - { - PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one succeding state must be drawn."); - goto errorInDatabase; - } + // at least one succeding state must be drawn + if (j == 0) { + PRINT(0, m, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber << ": At least one succeding state must be drawn."); + goto errorInDatabase; + } - // ply info must also be 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!"); - goto errorInDatabase; - } - break; + // ply info must also be 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!"); + goto errorInDatabase; + } + break; - case SKV_VALUE_INVALID: - // if setSituation() returned true but state value is invalid, then all following states must be invalid - for (i = 0; i < numPossibilities; i++) - { - if (subValueInDatabase[i] != SKV_VALUE_INVALID) - break; - } - 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."); - goto errorInDatabase; - } - // ply info must also be 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!"); - goto errorInDatabase; - } - break; - } - } - return TM_RETURN_VALUE_OK; + case SKV_VALUE_INVALID: + // if setSituation() returned true but state value is invalid, then all following states must be invalid + for (i = 0; i < numPossibilities; i++) { + if (subValueInDatabase[i] != SKV_VALUE_INVALID) + break; + } + 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."); + goto errorInDatabase; + } + // ply info must also be 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!"); + goto errorInDatabase; + } + break; + } + } + return TM_RETURN_VALUE_OK; errorInDatabase: - // terminate all threads - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + // terminate all threads + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; } //----------------------------------------------------------------------------- @@ -368,27 +319,27 @@ errorInDatabase: //----------------------------------------------------------------------------- bool MiniMax::testState(unsigned int layerNumber, unsigned int stateNumber) { - // locals - TestLayersVars tlVars; - bool result; + // locals + TestLayersVars tlVars; + bool result; - // prepare parameters for multithreading - tlVars.curThreadNo = 0; - tlVars.pMiniMax = this; - tlVars.layerNumber = layerNumber; - tlVars.statesProcessed = 0; - tlVars.subValueInDatabase = new TwoBit[maxNumBranches]; - tlVars.subPlyInfos = new PlyInfoVarType[maxNumBranches]; - tlVars.hasCurPlayerChanged = new bool[maxNumBranches]; + // prepare parameters for multithreading + tlVars.curThreadNo = 0; + tlVars.pMiniMax = this; + tlVars.layerNumber = layerNumber; + tlVars.statesProcessed = 0; + tlVars.subValueInDatabase = new TwoBit[maxNumBranches]; + tlVars.subPlyInfos = new PlyInfoVarType[maxNumBranches]; + tlVars.hasCurPlayerChanged = new bool[maxNumBranches]; - if (testLayerThreadProc(&tlVars, stateNumber) != TM_RETURN_VALUE_OK) - result = false; + if (testLayerThreadProc(&tlVars, stateNumber) != TM_RETURN_VALUE_OK) + result = false; - delete[] tlVars.subValueInDatabase; - delete[] tlVars.subPlyInfos; - delete[] tlVars.hasCurPlayerChanged; + delete[] tlVars.subValueInDatabase; + delete[] tlVars.subPlyInfos; + delete[] tlVars.hasCurPlayerChanged; - return result; + return result; } //----------------------------------------------------------------------------- @@ -397,72 +348,63 @@ bool MiniMax::testState(unsigned int layerNumber, unsigned int stateNumber) //----------------------------------------------------------------------------- bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber) { - // Locals - unsigned int curThreadNo; - unsigned int returnValue; + // Locals + unsigned int curThreadNo; + unsigned int returnValue; - // output - PRINT(1, this, endl << "*** Test each state in layer: " << layerNumber << " ***"); - PRINT(1, this, (getOutputInformation(layerNumber))); + // output + PRINT(1, this, endl << "*** Test each state in layer: " << layerNumber << " ***"); + PRINT(1, this, (getOutputInformation(layerNumber))); - // prepare parameters for multithreading - numStatesProcessed = 0; - curCalculationActionId = MM_ACTION_TESTING_LAYER; - TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; - for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) - { - tlVars[curThreadNo].curThreadNo = curThreadNo; - tlVars[curThreadNo].pMiniMax = this; - tlVars[curThreadNo].layerNumber = layerNumber; - tlVars[curThreadNo].statesProcessed = 0; - tlVars[curThreadNo].subValueInDatabase = new TwoBit[maxNumBranches]; - tlVars[curThreadNo].subPlyInfos = new PlyInfoVarType[maxNumBranches]; - tlVars[curThreadNo].hasCurPlayerChanged = new bool[maxNumBranches]; - } + // prepare parameters for multithreading + numStatesProcessed = 0; + curCalculationActionId = MM_ACTION_TESTING_LAYER; + TestLayersVars *tlVars = new TestLayersVars[threadManager.getNumThreads()]; + for (curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) { + tlVars[curThreadNo].curThreadNo = curThreadNo; + tlVars[curThreadNo].pMiniMax = this; + tlVars[curThreadNo].layerNumber = layerNumber; + tlVars[curThreadNo].statesProcessed = 0; + tlVars[curThreadNo].subValueInDatabase = new TwoBit[maxNumBranches]; + tlVars[curThreadNo].subPlyInfos = new PlyInfoVarType[maxNumBranches]; + tlVars[curThreadNo].hasCurPlayerChanged = new bool[maxNumBranches]; + } - // process each state in the current layer - returnValue = threadManager.executeParallelLoop(testSetSituationThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); - switch (returnValue) - { - case TM_RETURN_VALUE_OK: - case TM_RETURN_VALUE_EXECUTION_CANCELLED: - // reduce and delete thread specific data - for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) - { - numStatesProcessed += tlVars[curThreadNo].statesProcessed; - SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); - SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); - SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); - } - SAFE_DELETE_ARRAY(tlVars); - if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) - { - PRINT(0, this, "Main thread: Execution cancelled by user"); - return false; // ... better would be to return a cancel-specific value - } - else - { - break; - } - default: - case TM_RETURN_VALUE_INVALID_PARAM: - case TM_RETURN_VALUE_UNEXPECTED_ERROR: - return falseOrStop(); - } + // process each state in the current layer + returnValue = threadManager.executeParallelLoop(testSetSituationThreadProc, (void *)tlVars, sizeof(TestLayersVars), TM_SCHEDULE_STATIC, 0, layerStats[layerNumber].knotsInLayer - 1, 1); + switch (returnValue) { + case TM_RETURN_VALUE_OK: + case TM_RETURN_VALUE_EXECUTION_CANCELLED: + // reduce and delete thread specific data + for (numStatesProcessed = 0, curThreadNo = 0; curThreadNo < threadManager.getNumThreads(); curThreadNo++) { + numStatesProcessed += tlVars[curThreadNo].statesProcessed; + SAFE_DELETE_ARRAY(tlVars[curThreadNo].subValueInDatabase); + SAFE_DELETE_ARRAY(tlVars[curThreadNo].hasCurPlayerChanged); + SAFE_DELETE_ARRAY(tlVars[curThreadNo].subPlyInfos); + } + SAFE_DELETE_ARRAY(tlVars); + if (returnValue == TM_RETURN_VALUE_EXECUTION_CANCELLED) { + PRINT(0, this, "Main thread: Execution cancelled by user"); + return false; // ... better would be to return a cancel-specific value + } else { + break; + } + default: + case TM_RETURN_VALUE_INVALID_PARAM: + case TM_RETURN_VALUE_UNEXPECTED_ERROR: + return falseOrStop(); + } - // layer is not ok - if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) - { - PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); - return falseOrStop(); - // layer is ok - } - else - { - PRINT(1, this, " TEST PASSED !" << endl - << endl); - return true; - } + // layer is not ok + if (numStatesProcessed < layerStats[layerNumber].knotsInLayer) { + PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber); + return falseOrStop(); + // layer is ok + } else { + PRINT(1, this, " TEST PASSED !" << endl + << endl); + return true; + } } //----------------------------------------------------------------------------- @@ -471,90 +413,79 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber) //----------------------------------------------------------------------------- DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index) { - // locals - TestLayersVars *tlVars = (TestLayersVars *)pParameter; - MiniMax *m = tlVars->pMiniMax; - unsigned int *idPossibility; - void *pPossibilities; - void *pBackup; - unsigned int curPoss; - float floatValue; - StateAdress curState; - StateAdress subState; - Node knot; - TwoBit shortKnotValue = SKV_VALUE_GAME_DRAWN; - curState.layerNumber = tlVars->layerNumber; - curState.stateNumber = index; + // locals + TestLayersVars *tlVars = (TestLayersVars *)pParameter; + MiniMax *m = tlVars->pMiniMax; + unsigned int *idPossibility; + void *pPossibilities; + void *pBackup; + unsigned int curPoss; + float floatValue; + StateAdress curState; + StateAdress subState; + Node knot; + TwoBit shortKnotValue = SKV_VALUE_GAME_DRAWN; + curState.layerNumber = tlVars->layerNumber; + curState.stateNumber = index; - // output - tlVars->statesProcessed++; - if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) - { - m->numStatesProcessed += OUTPUT_EVERY_N_STATES; - PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[curState.layerNumber].knotsInLayer << " tested"); - } + // output + tlVars->statesProcessed++; + if (tlVars->statesProcessed % OUTPUT_EVERY_N_STATES == 0) { + m->numStatesProcessed += OUTPUT_EVERY_N_STATES; + PRINT(0, m, m->numStatesProcessed << " states of " << m->layerStats[curState.layerNumber].knotsInLayer << " tested"); + } - // set state - if (m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber)) - { - m->getValueOfSituation(tlVars->curThreadNo, floatValue, shortKnotValue); - } - else - { - shortKnotValue = SKV_VALUE_INVALID; - } + // set state + if (m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber)) { + m->getValueOfSituation(tlVars->curThreadNo, floatValue, shortKnotValue); + } else { + shortKnotValue = SKV_VALUE_INVALID; + } - // get number of possiblities - idPossibility = m->getPossibilities(tlVars->curThreadNo, &knot.numPossibilities, &knot.isOpponentLevel, &pPossibilities); + // get number of possiblities + idPossibility = m->getPossibilities(tlVars->curThreadNo, &knot.numPossibilities, &knot.isOpponentLevel, &pPossibilities); - // unable to move - if (knot.numPossibilities == 0) - { - 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."); - return m->falseOrStop(); - } - // moving is possible - } - else - { - 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."); - return m->falseOrStop(); - } + // unable to move + if (knot.numPossibilities == 0) { + 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."); + return m->falseOrStop(); + } + // moving is possible + } else { + 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."); + return m->falseOrStop(); + } - // check each possibility - for (curPoss = 0; curPoss < knot.numPossibilities; curPoss++) - { + // check each possibility + for (curPoss = 0; curPoss < knot.numPossibilities; curPoss++) { - // move - m->move(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, &pBackup, pPossibilities); + // move + m->move(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, &pBackup, pPossibilities); - // get state number of succeding state - unsigned int i; - m->getLayerAndStateNumber(tlVars->curThreadNo, i, subState.stateNumber); - subState.layerNumber = i; + // get state number of succeding state + unsigned int i; + m->getLayerAndStateNumber(tlVars->curThreadNo, i, subState.stateNumber); + subState.layerNumber = i; - // undo move - m->undo(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, pBackup, pPossibilities); + // undo move + m->undo(tlVars->curThreadNo, idPossibility[curPoss], knot.isOpponentLevel, pBackup, pPossibilities); - // state reached by move() must not be invalid - 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); - return m->falseOrStop(); - } - // set back to current state - m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber); - } - } - return TM_RETURN_VALUE_OK; + // state reached by move() must not be invalid + 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); + return m->falseOrStop(); + } + // set back to current state + m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber); + } + } + return TM_RETURN_VALUE_OK; - //errorInDatabase: - // terminate all threads - return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; + //errorInDatabase: + // terminate all threads + return TM_RETURN_VALUE_TERMINATE_ALL_THREADS; } //----------------------------------------------------------------------------- @@ -563,95 +494,89 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index) //----------------------------------------------------------------------------- bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber) { - // Locals - unsigned int threadNo = 0; - TwoBit shortValueInDatabase; - TwoBit shortValueOfSymState; - PlyInfoVarType numPliesTillCurState; - PlyInfoVarType numPliesTillSymState; - unsigned int stateNumber = 0; - unsigned int *symStateNumbers = nullptr; - unsigned int numSymmetricStates; - unsigned int i; + // Locals + unsigned int threadNo = 0; + TwoBit shortValueInDatabase; + TwoBit shortValueOfSymState; + PlyInfoVarType numPliesTillCurState; + PlyInfoVarType numPliesTillSymState; + unsigned int stateNumber = 0; + unsigned int *symStateNumbers = nullptr; + unsigned int numSymmetricStates; + unsigned int i; - // database open? - if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) - { - PRINT(0, this, "ERROR: Database files not open!"); - layerNumber = 0; - goto errorInDatabase; - } + // database open? + if (hFileShortKnotValues == nullptr || hFilePlyInfo == nullptr) { + PRINT(0, this, "ERROR: Database files not open!"); + layerNumber = 0; + goto errorInDatabase; + } - // layer completed ? - if (!layerStats[layerNumber].layerIsCompletedAndInFile) - { - PRINT(0, this, "ERROR: Layer not in file!"); - layerNumber = 0; - goto errorInDatabase; - } + // layer completed ? + if (!layerStats[layerNumber].layerIsCompletedAndInFile) { + PRINT(0, this, "ERROR: Layer not in file!"); + layerNumber = 0; + goto errorInDatabase; + } - // test if each state has symmetric states with the same value - PRINT(1, this, endl << "testIfSymmetricStatesHaveSameValue - TEST EACH STATE IN LAYER: " << layerNumber); - PRINT(1, this, (getOutputInformation(layerNumber))); - skvfHeader.completed = false; + // test if each state has symmetric states with the same value + PRINT(1, this, endl << "testIfSymmetricStatesHaveSameValue - TEST EACH STATE IN LAYER: " << layerNumber); + PRINT(1, this, (getOutputInformation(layerNumber))); + skvfHeader.completed = false; - for (layerInDatabase = false, stateNumber = 0; stateNumber < layerStats[layerNumber].knotsInLayer; stateNumber++) - { + for (layerInDatabase = false, stateNumber = 0; stateNumber < layerStats[layerNumber].knotsInLayer; stateNumber++) { - // output - if (stateNumber % OUTPUT_EVERY_N_STATES == 0) - PRINT(1, this, stateNumber << " states of " << layerStats[layerNumber].knotsInLayer << " tested"); + // output + if (stateNumber % OUTPUT_EVERY_N_STATES == 0) + PRINT(1, this, stateNumber << " states of " << layerStats[layerNumber].knotsInLayer << " tested"); - // situation already existend in database ? - readKnotValueFromDatabase(layerNumber, stateNumber, shortValueInDatabase); - readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); + // situation already existend in database ? + readKnotValueFromDatabase(layerNumber, stateNumber, shortValueInDatabase); + readPlyInfoFromDatabase(layerNumber, stateNumber, numPliesTillCurState); - // prepare the situation - if (!setSituation(threadNo, layerNumber, stateNumber)) - { + // prepare the situation + if (!setSituation(threadNo, layerNumber, stateNumber)) { - // when situation cannot be constructed then state must be marked as invalid in database - if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID) - goto errorInDatabase; - else - continue; - } + // when situation cannot be constructed then state must be marked as invalid in database + if (shortValueInDatabase != SKV_VALUE_INVALID || numPliesTillCurState != PLYINFO_VALUE_INVALID) + goto errorInDatabase; + else + continue; + } - // get numbers of symmetric states - getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers); + // get numbers of symmetric states + getSymStateNumWithDoubles(threadNo, &numSymmetricStates, &symStateNumbers); - // save value for all symmetric states - for (i = 0; i < numSymmetricStates; i++) - { + // save value for all symmetric states + for (i = 0; i < numSymmetricStates; i++) { - readKnotValueFromDatabase(layerNumber, symStateNumbers[i], shortValueOfSymState); - readPlyInfoFromDatabase(layerNumber, symStateNumbers[i], numPliesTillSymState); + readKnotValueFromDatabase(layerNumber, symStateNumbers[i], shortValueOfSymState); + 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); - setSituation(threadNo, layerNumber, stateNumber); - printBoard(threadNo, shortValueInDatabase); + PRINT(2, this, "current tested state " << stateNumber << " has value " << (int)shortValueInDatabase); + setSituation(threadNo, layerNumber, stateNumber); + printBoard(threadNo, shortValueInDatabase); - PRINT(1, this, ""); - PRINT(1, this, "symmetric state " << symStateNumbers[i] << " has value " << (int)shortValueOfSymState); - setSituation(threadNo, layerNumber, symStateNumbers[i]); - printBoard(threadNo, shortValueOfSymState); + PRINT(1, this, ""); + PRINT(1, this, "symmetric state " << symStateNumbers[i] << " has value " << (int)shortValueOfSymState); + setSituation(threadNo, layerNumber, symStateNumbers[i]); + printBoard(threadNo, shortValueOfSymState); - setSituation(threadNo, layerNumber, stateNumber); - } - } - } + setSituation(threadNo, layerNumber, stateNumber); + } + } + } - // layer is ok - PRINT(0, this, "TEST PASSED !"); - return true; + // layer is ok + PRINT(0, this, "TEST PASSED !"); + return true; errorInDatabase: - // layer is not ok - if (layerNumber) - PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber); - return falseOrStop(); + // layer is not ok + if (layerNumber) + PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber); + return falseOrStop(); } diff --git a/src/perfect/perfectAI.cpp b/src/perfect/perfectAI.cpp index 331da580..d9143077 100644 --- a/src/perfect/perfectAI.cpp +++ b/src/perfect/perfectAI.cpp @@ -1,170 +1,170 @@ /********************************************************************* - PerfectAI.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + PerfectAI.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "perfectAI.h" unsigned int soTableTurnLeft[] = { - 2, 14, 23, - 5, 13, 20, - 8, 12, 17, - 1, 4, 7, 16, 19, 22, - 6, 11, 15, - 3, 10, 18, - 0, 9, 21}; + 2, 14, 23, + 5, 13, 20, + 8, 12, 17, + 1, 4, 7, 16, 19, 22, + 6, 11, 15, + 3, 10, 18, + 0, 9, 21 }; unsigned int soTableDoNothing[] = { - 0, 1, 2, - 3, 4, 5, - 6, 7, 8, - 9, 10, 11, 12, 13, 14, - 15, 16, 17, - 18, 19, 20, - 21, 22, 23}; + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, + 9, 10, 11, 12, 13, 14, + 15, 16, 17, + 18, 19, 20, + 21, 22, 23 }; unsigned int soTableMirrorHori[] = { - 21, 22, 23, - 18, 19, 20, - 15, 16, 17, - 9, 10, 11, 12, 13, 14, - 6, 7, 8, - 3, 4, 5, - 0, 1, 2}; + 21, 22, 23, + 18, 19, 20, + 15, 16, 17, + 9, 10, 11, 12, 13, 14, + 6, 7, 8, + 3, 4, 5, + 0, 1, 2 }; unsigned int soTableTurn180[] = { - 23, 22, 21, - 20, 19, 18, - 17, 16, 15, - 14, 13, 12, 11, 10, 9, - 8, 7, 6, - 5, 4, 3, - 2, 1, 0}; + 23, 22, 21, + 20, 19, 18, + 17, 16, 15, + 14, 13, 12, 11, 10, 9, + 8, 7, 6, + 5, 4, 3, + 2, 1, 0 }; unsigned int soTableInvert[] = { - 6, 7, 8, - 3, 4, 5, - 0, 1, 2, - 11, 10, 9, 14, 13, 12, - 21, 22, 23, - 18, 19, 20, - 15, 16, 17}; + 6, 7, 8, + 3, 4, 5, + 0, 1, 2, + 11, 10, 9, 14, 13, 12, + 21, 22, 23, + 18, 19, 20, + 15, 16, 17 }; unsigned int soTableInvMirHori[] = { - 15, 16, 17, - 18, 19, 20, - 21, 22, 23, - 11, 10, 9, 14, 13, 12, - 0, 1, 2, - 3, 4, 5, - 6, 7, 8}; + 15, 16, 17, + 18, 19, 20, + 21, 22, 23, + 11, 10, 9, 14, 13, 12, + 0, 1, 2, + 3, 4, 5, + 6, 7, 8 }; unsigned int soTableInvMirVert[] = { - 8, 7, 6, - 5, 4, 3, - 2, 1, 0, - 12, 13, 14, 9, 10, 11, - 23, 22, 21, - 20, 19, 18, - 17, 16, 15}; + 8, 7, 6, + 5, 4, 3, + 2, 1, 0, + 12, 13, 14, 9, 10, 11, + 23, 22, 21, + 20, 19, 18, + 17, 16, 15 }; unsigned int soTableInvMirDiag1[] = { - 17, 12, 8, - 20, 13, 5, - 23, 14, 2, - 16, 19, 22, 1, 4, 7, - 21, 9, 0, - 18, 10, 3, - 15, 11, 6}; + 17, 12, 8, + 20, 13, 5, + 23, 14, 2, + 16, 19, 22, 1, 4, 7, + 21, 9, 0, + 18, 10, 3, + 15, 11, 6 }; unsigned int soTableInvMirDiag2[] = { - 6, 11, 15, - 3, 10, 18, - 0, 9, 21, - 7, 4, 1, 22, 19, 16, - 2, 14, 23, - 5, 13, 20, - 8, 12, 17}; + 6, 11, 15, + 3, 10, 18, + 0, 9, 21, + 7, 4, 1, 22, 19, 16, + 2, 14, 23, + 5, 13, 20, + 8, 12, 17 }; unsigned int soTableInvLeft[] = { - 8, 12, 17, - 5, 13, 20, - 2, 14, 23, - 7, 4, 1, 22, 19, 16, - 0, 9, 21, - 3, 10, 18, - 6, 11, 15}; + 8, 12, 17, + 5, 13, 20, + 2, 14, 23, + 7, 4, 1, 22, 19, 16, + 0, 9, 21, + 3, 10, 18, + 6, 11, 15 }; unsigned int soTableInvRight[] = { - 15, 11, 6, - 18, 10, 3, - 21, 9, 0, - 16, 19, 22, 1, 4, 7, - 23, 14, 2, - 20, 13, 5, - 17, 12, 8}; + 15, 11, 6, + 18, 10, 3, + 21, 9, 0, + 16, 19, 22, 1, 4, 7, + 23, 14, 2, + 20, 13, 5, + 17, 12, 8 }; unsigned int soTableInv180[] = { - 17, 16, 15, - 20, 19, 18, - 23, 22, 21, - 12, 13, 14, 9, 10, 11, - 2, 1, 0, - 5, 4, 3, - 8, 7, 6}; + 17, 16, 15, + 20, 19, 18, + 23, 22, 21, + 12, 13, 14, 9, 10, 11, + 2, 1, 0, + 5, 4, 3, + 8, 7, 6 }; unsigned int soTableMirrorDiag1[] = { - 0, 9, 21, - 3, 10, 18, - 6, 11, 15, - 1, 4, 7, 16, 19, 22, - 8, 12, 17, - 5, 13, 20, - 2, 14, 23}; + 0, 9, 21, + 3, 10, 18, + 6, 11, 15, + 1, 4, 7, 16, 19, 22, + 8, 12, 17, + 5, 13, 20, + 2, 14, 23 }; unsigned int soTableTurnRight[] = { - 21, 9, 0, - 18, 10, 3, - 15, 11, 6, - 22, 19, 16, 7, 4, 1, - 17, 12, 8, - 20, 13, 5, - 23, 14, 2}; + 21, 9, 0, + 18, 10, 3, + 15, 11, 6, + 22, 19, 16, 7, 4, 1, + 17, 12, 8, + 20, 13, 5, + 23, 14, 2 }; unsigned int soTableMirrorVert[] = { - 2, 1, 0, - 5, 4, 3, - 8, 7, 6, - 14, 13, 12, 11, 10, 9, - 17, 16, 15, - 20, 19, 18, - 23, 22, 21}; + 2, 1, 0, + 5, 4, 3, + 8, 7, 6, + 14, 13, 12, 11, 10, 9, + 17, 16, 15, + 20, 19, 18, + 23, 22, 21 }; unsigned int soTableMirrorDiag2[] = { - 23, 14, 2, - 20, 13, 5, - 17, 12, 8, - 22, 19, 16, 7, 4, 1, - 15, 11, 6, - 18, 10, 3, - 21, 9, 0}; + 23, 14, 2, + 20, 13, 5, + 17, 12, 8, + 22, 19, 16, 7, 4, 1, + 15, 11, 6, + 18, 10, 3, + 21, 9, 0 }; // define the four groups -unsigned int squareIndexGroupA[] = {3, 5, 20, 18}; -unsigned int squareIndexGroupB[] = {4, 13, 19, 10}; -unsigned int squareIndexGroupC[] = {0, 2, 23, 21, 6, 8, 17, 15}; -unsigned int squareIndexGroupD[] = {1, 7, 14, 12, 22, 16, 9, 11}; +unsigned int squareIndexGroupA[] = { 3, 5, 20, 18 }; +unsigned int squareIndexGroupB[] = { 4, 13, 19, 10 }; +unsigned int squareIndexGroupC[] = { 0, 2, 23, 21, 6, 8, 17, 15 }; +unsigned int squareIndexGroupD[] = { 1, 7, 14, 12, 22, 16, 9, 11 }; -unsigned int fieldPosIsOfGroup[] = {GROUP_C, GROUP_D, GROUP_C, - GROUP_A, GROUP_B, GROUP_A, - GROUP_C, GROUP_D, GROUP_C, - GROUP_D, GROUP_B, GROUP_D, GROUP_D, GROUP_B, GROUP_D, - GROUP_C, GROUP_D, GROUP_C, - GROUP_A, GROUP_B, GROUP_A, - GROUP_C, GROUP_D, GROUP_C}; +unsigned int fieldPosIsOfGroup[] = { GROUP_C, GROUP_D, GROUP_C, + GROUP_A, GROUP_B, GROUP_A, + GROUP_C, GROUP_D, GROUP_C, + GROUP_D, GROUP_B, GROUP_D, GROUP_D, GROUP_B, GROUP_D, + GROUP_C, GROUP_D, GROUP_C, + GROUP_A, GROUP_B, GROUP_A, + GROUP_C, GROUP_D, GROUP_C }; //----------------------------------------------------------------------------- // Name: PerfectAI() @@ -172,518 +172,467 @@ unsigned int fieldPosIsOfGroup[] = {GROUP_C, GROUP_D, GROUP_C, //----------------------------------------------------------------------------- PerfectAI::PerfectAI(const char *directory) { - // loacls - unsigned int i, a, b, c, totalNumStones; - unsigned int wCD, bCD, wAB, bAB; - unsigned int stateAB, stateCD, symStateCD, layerNum; - unsigned int myField[fieldStruct::size]; - unsigned int symField[fieldStruct::size]; - unsigned int *originalStateCD_tmp[10][10]; - DWORD dwBytesRead = 0; - DWORD dwBytesWritten = 0; - HANDLE hFilePreCalcVars; - stringstream ssPreCalcVarsFilePath; - PreCalcedVarsFileHeader preCalcVarsHeader; + // loacls + unsigned int i, a, b, c, totalNumStones; + unsigned int wCD, bCD, wAB, bAB; + unsigned int stateAB, stateCD, symStateCD, layerNum; + unsigned int myField[fieldStruct::size]; + unsigned int symField[fieldStruct::size]; + unsigned int *originalStateCD_tmp[10][10]; + DWORD dwBytesRead = 0; + DWORD dwBytesWritten = 0; + HANDLE hFilePreCalcVars; + stringstream ssPreCalcVarsFilePath; + PreCalcedVarsFileHeader preCalcVarsHeader; - // - threadVars = new ThreadVars[getNumThreads()]; - for (unsigned int curThread = 0; curThread < getNumThreads(); curThread++) - { - threadVars[curThread].parent = this; - threadVars[curThread].field = &dummyField; - threadVars[curThread].possibilities = new Possibility[MAX_DEPTH_OF_TREE + 1]; - threadVars[curThread].oldStates = new Backup[MAX_DEPTH_OF_TREE + 1]; - threadVars[curThread].idPossibilities = new unsigned int[(MAX_DEPTH_OF_TREE + 1) * MAX_NUM_POS_MOVES]; - } + // + threadVars = new ThreadVars[getNumThreads()]; + for (unsigned int curThread = 0; curThread < getNumThreads(); curThread++) { + threadVars[curThread].parent = this; + threadVars[curThread].field = &dummyField; + threadVars[curThread].possibilities = new Possibility[MAX_DEPTH_OF_TREE + 1]; + threadVars[curThread].oldStates = new Backup[MAX_DEPTH_OF_TREE + 1]; + threadVars[curThread].idPossibilities = new unsigned int[(MAX_DEPTH_OF_TREE + 1) * MAX_NUM_POS_MOVES]; + } - // Open File, which contains the precalculated vars - if (strlen(directory) && PathFileExistsA(directory)) - { - ssPreCalcVarsFilePath << directory << "\\"; - } - ssPreCalcVarsFilePath << "preCalculatedVars.dat"; - hFilePreCalcVars = CreateFileA(ssPreCalcVarsFilePath.str().c_str(), GENERIC_READ /*| GENERIC_WRITE*/, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - ReadFile(hFilePreCalcVars, &preCalcVarsHeader, sizeof(PreCalcedVarsFileHeader), &dwBytesRead, nullptr); + // Open File, which contains the precalculated vars + if (strlen(directory) && PathFileExistsA(directory)) { + ssPreCalcVarsFilePath << directory << "\\"; + } + ssPreCalcVarsFilePath << "preCalculatedVars.dat"; + hFilePreCalcVars = CreateFileA(ssPreCalcVarsFilePath.str().c_str(), GENERIC_READ /*| GENERIC_WRITE*/, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + ReadFile(hFilePreCalcVars, &preCalcVarsHeader, sizeof(PreCalcedVarsFileHeader), &dwBytesRead, nullptr); - // vars already stored in file? - if (dwBytesRead) - { + // vars already stored in file? + if (dwBytesRead) { - // Read from file - ReadFile(hFilePreCalcVars, layer, sizeof(Layer) * NUM_LAYERS, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, layerIndex, sizeof(unsigned int) * 2 * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, anzahlStellungenAB, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, anzahlStellungenCD, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, indexAB, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, indexCD, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, symmetryOperationCD, sizeof(unsigned char) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, powerOfThree, sizeof(unsigned int) * (numSquaresGroupC + numSquaresGroupD), &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, symmetryOperationTable, sizeof(unsigned int) * fieldStruct::size * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, reverseSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, concSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, mOverN, sizeof(unsigned int) * (fieldStruct::size + 1) * (fieldStruct::size + 1), &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); - ReadFile(hFilePreCalcVars, incidencesValuesSubMoves, sizeof(unsigned int) * 4 * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); + // Read from file + ReadFile(hFilePreCalcVars, layer, sizeof(Layer) * NUM_LAYERS, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, layerIndex, sizeof(unsigned int) * 2 * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, anzahlStellungenAB, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, anzahlStellungenCD, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, indexAB, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, indexCD, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, symmetryOperationCD, sizeof(unsigned char) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, powerOfThree, sizeof(unsigned int) * (numSquaresGroupC + numSquaresGroupD), &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, symmetryOperationTable, sizeof(unsigned int) * fieldStruct::size * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, reverseSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, concSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS * NUM_SYM_OPERATIONS, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, mOverN, sizeof(unsigned int) * (fieldStruct::size + 1) * (fieldStruct::size + 1), &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); + ReadFile(hFilePreCalcVars, incidencesValuesSubMoves, sizeof(unsigned int) * 4 * fieldStruct::size * fieldStruct::size, &dwBytesRead, nullptr); - // process originalStateAB[][] - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupA + numSquaresGroupB) - continue; - originalStateAB[a][b] = new unsigned int[anzahlStellungenAB[a][b]]; - ReadFile(hFilePreCalcVars, originalStateAB[a][b], sizeof(unsigned int) * anzahlStellungenAB[a][b], &dwBytesRead, nullptr); - } - } + // process originalStateAB[][] + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupA + numSquaresGroupB) + continue; + originalStateAB[a][b] = new unsigned int[anzahlStellungenAB[a][b]]; + ReadFile(hFilePreCalcVars, originalStateAB[a][b], sizeof(unsigned int) * anzahlStellungenAB[a][b], &dwBytesRead, nullptr); + } + } - // process originalStateCD[][] - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupC + numSquaresGroupD) - continue; - originalStateCD[a][b] = new unsigned int[anzahlStellungenCD[a][b]]; - ReadFile(hFilePreCalcVars, originalStateCD[a][b], sizeof(unsigned int) * anzahlStellungenCD[a][b], &dwBytesRead, nullptr); - } - } + // process originalStateCD[][] + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupC + numSquaresGroupD) + continue; + originalStateCD[a][b] = new unsigned int[anzahlStellungenCD[a][b]]; + ReadFile(hFilePreCalcVars, originalStateCD[a][b], sizeof(unsigned int) * anzahlStellungenCD[a][b], &dwBytesRead, nullptr); + } + } - // calculate vars and save into file - } - else - { + // calculate vars and save into file + } else { - // calc mOverN - for (a = 0; a <= fieldStruct::size; a++) - { - for (b = 0; b <= fieldStruct::size; b++) - { - mOverN[a][b] = (unsigned int)mOverN_Function(a, b); - } - } + // calc mOverN + for (a = 0; a <= fieldStruct::size; a++) { + for (b = 0; b <= fieldStruct::size; b++) { + mOverN[a][b] = (unsigned int)mOverN_Function(a, b); + } + } - // reset - for (i = 0; i < fieldStruct::size * fieldStruct::size; i++) - { - plyInfoForOutput[i] = PLYINFO_VALUE_INVALID; - valueOfMove[i] = SKV_VALUE_INVALID; - incidencesValuesSubMoves[i][SKV_VALUE_INVALID] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_LOST] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_DRAWN] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_WON] = 0; - } + // reset + for (i = 0; i < fieldStruct::size * fieldStruct::size; i++) { + plyInfoForOutput[i] = PLYINFO_VALUE_INVALID; + valueOfMove[i] = SKV_VALUE_INVALID; + incidencesValuesSubMoves[i][SKV_VALUE_INVALID] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_LOST] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_DRAWN] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_WON] = 0; + } - // power of three - for (powerOfThree[0] = 1, i = 1; i < numSquaresGroupC + numSquaresGroupD; i++) - powerOfThree[i] = 3 * powerOfThree[i - 1]; + // power of three + for (powerOfThree[0] = 1, i = 1; i < numSquaresGroupC + numSquaresGroupD; i++) + powerOfThree[i] = 3 * powerOfThree[i - 1]; - // symmetry operation table - for (i = 0; i < fieldStruct::size; i++) - { - symmetryOperationTable[SO_TURN_LEFT][i] = soTableTurnLeft[i]; - symmetryOperationTable[SO_TURN_180][i] = soTableTurn180[i]; - symmetryOperationTable[SO_TURN_RIGHT][i] = soTableTurnRight[i]; - symmetryOperationTable[SO_DO_NOTHING][i] = soTableDoNothing[i]; - symmetryOperationTable[SO_INVERT][i] = soTableInvert[i]; - symmetryOperationTable[SO_MIRROR_VERT][i] = soTableMirrorVert[i]; - symmetryOperationTable[SO_MIRROR_HORI][i] = soTableMirrorHori[i]; - symmetryOperationTable[SO_MIRROR_DIAG_1][i] = soTableMirrorDiag1[i]; - symmetryOperationTable[SO_MIRROR_DIAG_2][i] = soTableMirrorDiag2[i]; - symmetryOperationTable[SO_INV_LEFT][i] = soTableInvLeft[i]; - symmetryOperationTable[SO_INV_RIGHT][i] = soTableInvRight[i]; - symmetryOperationTable[SO_INV_180][i] = soTableInv180[i]; - symmetryOperationTable[SO_INV_MIR_VERT][i] = soTableInvMirHori[i]; - symmetryOperationTable[SO_INV_MIR_HORI][i] = soTableInvMirVert[i]; - symmetryOperationTable[SO_INV_MIR_DIAG_1][i] = soTableInvMirDiag1[i]; - symmetryOperationTable[SO_INV_MIR_DIAG_2][i] = soTableInvMirDiag2[i]; - } + // symmetry operation table + for (i = 0; i < fieldStruct::size; i++) { + symmetryOperationTable[SO_TURN_LEFT][i] = soTableTurnLeft[i]; + symmetryOperationTable[SO_TURN_180][i] = soTableTurn180[i]; + symmetryOperationTable[SO_TURN_RIGHT][i] = soTableTurnRight[i]; + symmetryOperationTable[SO_DO_NOTHING][i] = soTableDoNothing[i]; + symmetryOperationTable[SO_INVERT][i] = soTableInvert[i]; + symmetryOperationTable[SO_MIRROR_VERT][i] = soTableMirrorVert[i]; + symmetryOperationTable[SO_MIRROR_HORI][i] = soTableMirrorHori[i]; + symmetryOperationTable[SO_MIRROR_DIAG_1][i] = soTableMirrorDiag1[i]; + symmetryOperationTable[SO_MIRROR_DIAG_2][i] = soTableMirrorDiag2[i]; + symmetryOperationTable[SO_INV_LEFT][i] = soTableInvLeft[i]; + symmetryOperationTable[SO_INV_RIGHT][i] = soTableInvRight[i]; + symmetryOperationTable[SO_INV_180][i] = soTableInv180[i]; + symmetryOperationTable[SO_INV_MIR_VERT][i] = soTableInvMirHori[i]; + symmetryOperationTable[SO_INV_MIR_HORI][i] = soTableInvMirVert[i]; + symmetryOperationTable[SO_INV_MIR_DIAG_1][i] = soTableInvMirDiag1[i]; + symmetryOperationTable[SO_INV_MIR_DIAG_2][i] = soTableInvMirDiag2[i]; + } - // reverse symmetrie operation - reverseSymOperation[SO_TURN_LEFT] = SO_TURN_RIGHT; - reverseSymOperation[SO_TURN_180] = SO_TURN_180; - reverseSymOperation[SO_TURN_RIGHT] = SO_TURN_LEFT; - reverseSymOperation[SO_DO_NOTHING] = SO_DO_NOTHING; - reverseSymOperation[SO_INVERT] = SO_INVERT; - reverseSymOperation[SO_MIRROR_VERT] = SO_MIRROR_VERT; - reverseSymOperation[SO_MIRROR_HORI] = SO_MIRROR_HORI; - reverseSymOperation[SO_MIRROR_DIAG_1] = SO_MIRROR_DIAG_1; - reverseSymOperation[SO_MIRROR_DIAG_2] = SO_MIRROR_DIAG_2; - reverseSymOperation[SO_INV_LEFT] = SO_INV_RIGHT; - reverseSymOperation[SO_INV_RIGHT] = SO_INV_LEFT; - reverseSymOperation[SO_INV_180] = SO_INV_180; - reverseSymOperation[SO_INV_MIR_VERT] = SO_INV_MIR_VERT; - reverseSymOperation[SO_INV_MIR_HORI] = SO_INV_MIR_HORI; - reverseSymOperation[SO_INV_MIR_DIAG_1] = SO_INV_MIR_DIAG_1; - reverseSymOperation[SO_INV_MIR_DIAG_2] = SO_INV_MIR_DIAG_2; + // reverse symmetrie operation + reverseSymOperation[SO_TURN_LEFT] = SO_TURN_RIGHT; + reverseSymOperation[SO_TURN_180] = SO_TURN_180; + reverseSymOperation[SO_TURN_RIGHT] = SO_TURN_LEFT; + reverseSymOperation[SO_DO_NOTHING] = SO_DO_NOTHING; + reverseSymOperation[SO_INVERT] = SO_INVERT; + reverseSymOperation[SO_MIRROR_VERT] = SO_MIRROR_VERT; + reverseSymOperation[SO_MIRROR_HORI] = SO_MIRROR_HORI; + reverseSymOperation[SO_MIRROR_DIAG_1] = SO_MIRROR_DIAG_1; + reverseSymOperation[SO_MIRROR_DIAG_2] = SO_MIRROR_DIAG_2; + reverseSymOperation[SO_INV_LEFT] = SO_INV_RIGHT; + reverseSymOperation[SO_INV_RIGHT] = SO_INV_LEFT; + reverseSymOperation[SO_INV_180] = SO_INV_180; + reverseSymOperation[SO_INV_MIR_VERT] = SO_INV_MIR_VERT; + reverseSymOperation[SO_INV_MIR_HORI] = SO_INV_MIR_HORI; + reverseSymOperation[SO_INV_MIR_DIAG_1] = SO_INV_MIR_DIAG_1; + reverseSymOperation[SO_INV_MIR_DIAG_2] = SO_INV_MIR_DIAG_2; - // concatenated symmetry operations - for (a = 0; a < NUM_SYM_OPERATIONS; a++) - { - for (b = 0; b < NUM_SYM_OPERATIONS; b++) - { + // concatenated symmetry operations + for (a = 0; a < NUM_SYM_OPERATIONS; a++) { + for (b = 0; b < NUM_SYM_OPERATIONS; b++) { - // test each symmetry operation - for (c = 0; c < NUM_SYM_OPERATIONS; c++) - { + // test each symmetry operation + for (c = 0; c < NUM_SYM_OPERATIONS; c++) { - // look if b(a(state)) == c(state) - for (i = 0; i < fieldStruct::size; i++) - { - if (symmetryOperationTable[c][i] != symmetryOperationTable[a][symmetryOperationTable[b][i]]) - break; - } + // look if b(a(state)) == c(state) + for (i = 0; i < fieldStruct::size; i++) { + if (symmetryOperationTable[c][i] != symmetryOperationTable[a][symmetryOperationTable[b][i]]) + break; + } - // match found? - if (i == fieldStruct::size) - { - concSymOperation[a][b] = c; - break; - } - } + // match found? + if (i == fieldStruct::size) { + concSymOperation[a][b] = c; + break; + } + } - // no match found - if (c == NUM_SYM_OPERATIONS) - { - cout << endl - << "ERROR IN SYMMETRY-OPERATIONS!" << endl; - } - } - } + // no match found + if (c == NUM_SYM_OPERATIONS) { + cout << endl + << "ERROR IN SYMMETRY-OPERATIONS!" << endl; + } + } + } - // group A&B // + // group A&B // - // reserve memory - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { + // reserve memory + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { - if (a + b > numSquaresGroupA + numSquaresGroupB) - continue; + if (a + b > numSquaresGroupA + numSquaresGroupB) + continue; - anzahlStellungenAB[a][b] = mOverN[numSquaresGroupA + numSquaresGroupB][a] * mOverN[numSquaresGroupA + numSquaresGroupB - a][b]; - originalStateAB[a][b] = new unsigned int[anzahlStellungenAB[a][b]]; - anzahlStellungenAB[a][b] = 0; - } - } + anzahlStellungenAB[a][b] = mOverN[numSquaresGroupA + numSquaresGroupB][a] * mOverN[numSquaresGroupA + numSquaresGroupB - a][b]; + originalStateAB[a][b] = new unsigned int[anzahlStellungenAB[a][b]]; + anzahlStellungenAB[a][b] = 0; + } + } - // mark all indexCD as not indexed - for (stateAB = 0; stateAB < MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B; stateAB++) - indexAB[stateAB] = NOT_INDEXED; + // mark all indexCD as not indexed + for (stateAB = 0; stateAB < MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B; stateAB++) + indexAB[stateAB] = NOT_INDEXED; - for (stateAB = 0; stateAB < MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B; stateAB++) - { + for (stateAB = 0; stateAB < MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B; stateAB++) { - // new state ? - if (indexAB[stateAB] == NOT_INDEXED) - { + // new state ? + if (indexAB[stateAB] == NOT_INDEXED) { - // zero board - for (i = 0; i < fieldStruct::size; i++) - myField[i] = FREE_SQUARE; + // zero board + for (i = 0; i < fieldStruct::size; i++) + myField[i] = FREE_SQUARE; - // make board - myField[squareIndexGroupA[0]] = (stateAB / powerOfThree[7]) % 3; - myField[squareIndexGroupA[1]] = (stateAB / powerOfThree[6]) % 3; - myField[squareIndexGroupA[2]] = (stateAB / powerOfThree[5]) % 3; - myField[squareIndexGroupA[3]] = (stateAB / powerOfThree[4]) % 3; - myField[squareIndexGroupB[4]] = (stateAB / powerOfThree[3]) % 3; - myField[squareIndexGroupB[5]] = (stateAB / powerOfThree[2]) % 3; - myField[squareIndexGroupB[6]] = (stateAB / powerOfThree[1]) % 3; - myField[squareIndexGroupB[7]] = (stateAB / powerOfThree[0]) % 3; + // make board + myField[squareIndexGroupA[0]] = (stateAB / powerOfThree[7]) % 3; + myField[squareIndexGroupA[1]] = (stateAB / powerOfThree[6]) % 3; + myField[squareIndexGroupA[2]] = (stateAB / powerOfThree[5]) % 3; + myField[squareIndexGroupA[3]] = (stateAB / powerOfThree[4]) % 3; + myField[squareIndexGroupB[4]] = (stateAB / powerOfThree[3]) % 3; + myField[squareIndexGroupB[5]] = (stateAB / powerOfThree[2]) % 3; + myField[squareIndexGroupB[6]] = (stateAB / powerOfThree[1]) % 3; + myField[squareIndexGroupB[7]] = (stateAB / powerOfThree[0]) % 3; - // count black and white stones - for (a = 0, i = 0; i < fieldStruct::size; i++) - if (myField[i] == WHITE_STONE) - a++; - for (b = 0, i = 0; i < fieldStruct::size; i++) - if (myField[i] == BLACK_STONE) - b++; + // count black and white stones + for (a = 0, i = 0; i < fieldStruct::size; i++) + if (myField[i] == WHITE_STONE) + a++; + for (b = 0, i = 0; i < fieldStruct::size; i++) + if (myField[i] == BLACK_STONE) + b++; - // condition - if (a + b > numSquaresGroupA + numSquaresGroupB) - continue; + // condition + if (a + b > numSquaresGroupA + numSquaresGroupB) + continue; - // mark original state - indexAB[stateAB] = anzahlStellungenAB[a][b]; - originalStateAB[a][b][anzahlStellungenAB[a][b]] = stateAB; + // mark original state + indexAB[stateAB] = anzahlStellungenAB[a][b]; + originalStateAB[a][b][anzahlStellungenAB[a][b]] = stateAB; - // state counter - anzahlStellungenAB[a][b]++; - } - } + // state counter + anzahlStellungenAB[a][b]++; + } + } - // group C&D // + // group C&D // - // reserve memory - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupC + numSquaresGroupD) - continue; - originalStateCD_tmp[a][b] = new unsigned int[mOverN[numSquaresGroupC + numSquaresGroupD][a] * mOverN[numSquaresGroupC + numSquaresGroupD - a][b]]; - anzahlStellungenCD[a][b] = 0; - } - } + // reserve memory + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupC + numSquaresGroupD) + continue; + originalStateCD_tmp[a][b] = new unsigned int[mOverN[numSquaresGroupC + numSquaresGroupD][a] * mOverN[numSquaresGroupC + numSquaresGroupD - a][b]]; + anzahlStellungenCD[a][b] = 0; + } + } - // mark all indexCD as not indexed - memset(indexCD, NOT_INDEXED, 4 * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D); + // mark all indexCD as not indexed + memset(indexCD, NOT_INDEXED, 4 * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D); - for (stateCD = 0; stateCD < MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D; stateCD++) - { + for (stateCD = 0; stateCD < MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D; stateCD++) { - // new state ? - if (indexCD[stateCD] == NOT_INDEXED) - { + // new state ? + if (indexCD[stateCD] == NOT_INDEXED) { - // zero board - for (i = 0; i < fieldStruct::size; i++) - myField[i] = FREE_SQUARE; + // zero board + for (i = 0; i < fieldStruct::size; i++) + myField[i] = FREE_SQUARE; - // make board - myField[squareIndexGroupC[0]] = (stateCD / powerOfThree[15]) % 3; - myField[squareIndexGroupC[1]] = (stateCD / powerOfThree[14]) % 3; - myField[squareIndexGroupC[2]] = (stateCD / powerOfThree[13]) % 3; - myField[squareIndexGroupC[3]] = (stateCD / powerOfThree[12]) % 3; - myField[squareIndexGroupC[4]] = (stateCD / powerOfThree[11]) % 3; - myField[squareIndexGroupC[5]] = (stateCD / powerOfThree[10]) % 3; - myField[squareIndexGroupC[6]] = (stateCD / powerOfThree[9]) % 3; - myField[squareIndexGroupC[7]] = (stateCD / powerOfThree[8]) % 3; - myField[squareIndexGroupD[0]] = (stateCD / powerOfThree[7]) % 3; - myField[squareIndexGroupD[1]] = (stateCD / powerOfThree[6]) % 3; - myField[squareIndexGroupD[2]] = (stateCD / powerOfThree[5]) % 3; - myField[squareIndexGroupD[3]] = (stateCD / powerOfThree[4]) % 3; - myField[squareIndexGroupD[4]] = (stateCD / powerOfThree[3]) % 3; - myField[squareIndexGroupD[5]] = (stateCD / powerOfThree[2]) % 3; - myField[squareIndexGroupD[6]] = (stateCD / powerOfThree[1]) % 3; - myField[squareIndexGroupD[7]] = (stateCD / powerOfThree[0]) % 3; + // make board + myField[squareIndexGroupC[0]] = (stateCD / powerOfThree[15]) % 3; + myField[squareIndexGroupC[1]] = (stateCD / powerOfThree[14]) % 3; + myField[squareIndexGroupC[2]] = (stateCD / powerOfThree[13]) % 3; + myField[squareIndexGroupC[3]] = (stateCD / powerOfThree[12]) % 3; + myField[squareIndexGroupC[4]] = (stateCD / powerOfThree[11]) % 3; + myField[squareIndexGroupC[5]] = (stateCD / powerOfThree[10]) % 3; + myField[squareIndexGroupC[6]] = (stateCD / powerOfThree[9]) % 3; + myField[squareIndexGroupC[7]] = (stateCD / powerOfThree[8]) % 3; + myField[squareIndexGroupD[0]] = (stateCD / powerOfThree[7]) % 3; + myField[squareIndexGroupD[1]] = (stateCD / powerOfThree[6]) % 3; + myField[squareIndexGroupD[2]] = (stateCD / powerOfThree[5]) % 3; + myField[squareIndexGroupD[3]] = (stateCD / powerOfThree[4]) % 3; + myField[squareIndexGroupD[4]] = (stateCD / powerOfThree[3]) % 3; + myField[squareIndexGroupD[5]] = (stateCD / powerOfThree[2]) % 3; + myField[squareIndexGroupD[6]] = (stateCD / powerOfThree[1]) % 3; + myField[squareIndexGroupD[7]] = (stateCD / powerOfThree[0]) % 3; - // count black and white stones - for (a = 0, i = 0; i < fieldStruct::size; i++) - if (myField[i] == WHITE_STONE) - a++; - for (b = 0, i = 0; i < fieldStruct::size; i++) - if (myField[i] == BLACK_STONE) - b++; + // count black and white stones + for (a = 0, i = 0; i < fieldStruct::size; i++) + if (myField[i] == WHITE_STONE) + a++; + for (b = 0, i = 0; i < fieldStruct::size; i++) + if (myField[i] == BLACK_STONE) + b++; - // condition - if (a + b > numSquaresGroupC + numSquaresGroupD) - continue; - if (a > NUM_STONES_PER_PLAYER) - continue; - if (b > NUM_STONES_PER_PLAYER) - continue; + // condition + if (a + b > numSquaresGroupC + numSquaresGroupD) + continue; + if (a > NUM_STONES_PER_PLAYER) + continue; + if (b > NUM_STONES_PER_PLAYER) + continue; - // mark original state - indexCD[stateCD] = anzahlStellungenCD[a][b]; - symmetryOperationCD[stateCD] = SO_DO_NOTHING; - originalStateCD_tmp[a][b][anzahlStellungenCD[a][b]] = stateCD; + // mark original state + indexCD[stateCD] = anzahlStellungenCD[a][b]; + symmetryOperationCD[stateCD] = SO_DO_NOTHING; + originalStateCD_tmp[a][b][anzahlStellungenCD[a][b]] = stateCD; - // mark all symmetric states - for (i = 0; i < NUM_SYM_OPERATIONS; i++) - { + // mark all symmetric states + for (i = 0; i < NUM_SYM_OPERATIONS; i++) { - applySymmetrieOperationOnField(i, myField, symField); + applySymmetrieOperationOnField(i, myField, symField); - symStateCD = symField[squareIndexGroupC[0]] * powerOfThree[15] + symField[squareIndexGroupC[1]] * powerOfThree[14] + symField[squareIndexGroupC[2]] * powerOfThree[13] + symField[squareIndexGroupC[3]] * powerOfThree[12] + symField[squareIndexGroupC[4]] * powerOfThree[11] + symField[squareIndexGroupC[5]] * powerOfThree[10] + symField[squareIndexGroupC[6]] * powerOfThree[9] + symField[squareIndexGroupC[7]] * powerOfThree[8] + symField[squareIndexGroupD[0]] * powerOfThree[7] + symField[squareIndexGroupD[1]] * powerOfThree[6] + symField[squareIndexGroupD[2]] * powerOfThree[5] + symField[squareIndexGroupD[3]] * powerOfThree[4] + symField[squareIndexGroupD[4]] * powerOfThree[3] + symField[squareIndexGroupD[5]] * powerOfThree[2] + symField[squareIndexGroupD[6]] * powerOfThree[1] + symField[squareIndexGroupD[7]] * powerOfThree[0]; + symStateCD = symField[squareIndexGroupC[0]] * powerOfThree[15] + symField[squareIndexGroupC[1]] * powerOfThree[14] + symField[squareIndexGroupC[2]] * powerOfThree[13] + symField[squareIndexGroupC[3]] * powerOfThree[12] + symField[squareIndexGroupC[4]] * powerOfThree[11] + symField[squareIndexGroupC[5]] * powerOfThree[10] + symField[squareIndexGroupC[6]] * powerOfThree[9] + symField[squareIndexGroupC[7]] * powerOfThree[8] + symField[squareIndexGroupD[0]] * powerOfThree[7] + symField[squareIndexGroupD[1]] * powerOfThree[6] + symField[squareIndexGroupD[2]] * powerOfThree[5] + symField[squareIndexGroupD[3]] * powerOfThree[4] + symField[squareIndexGroupD[4]] * powerOfThree[3] + symField[squareIndexGroupD[5]] * powerOfThree[2] + symField[squareIndexGroupD[6]] * powerOfThree[1] + symField[squareIndexGroupD[7]] * powerOfThree[0]; - if (stateCD != symStateCD) - { - indexCD[symStateCD] = anzahlStellungenCD[a][b]; - symmetryOperationCD[symStateCD] = reverseSymOperation[i]; - } - } + if (stateCD != symStateCD) { + indexCD[symStateCD] = anzahlStellungenCD[a][b]; + symmetryOperationCD[symStateCD] = reverseSymOperation[i]; + } + } - // state counter - anzahlStellungenCD[a][b]++; - } - } + // state counter + anzahlStellungenCD[a][b]++; + } + } - // copy from originalStateCD_tmp to originalStateCD - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupC + numSquaresGroupD) - continue; - originalStateCD[a][b] = new unsigned int[anzahlStellungenCD[a][b]]; - for (i = 0; i < anzahlStellungenCD[a][b]; i++) - originalStateCD[a][b][i] = originalStateCD_tmp[a][b][i]; - SAFE_DELETE_ARRAY(originalStateCD_tmp[a][b]); - } - } + // copy from originalStateCD_tmp to originalStateCD + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupC + numSquaresGroupD) + continue; + originalStateCD[a][b] = new unsigned int[anzahlStellungenCD[a][b]]; + for (i = 0; i < anzahlStellungenCD[a][b]; i++) + originalStateCD[a][b][i] = originalStateCD_tmp[a][b][i]; + SAFE_DELETE_ARRAY(originalStateCD_tmp[a][b]); + } + } - // moving phase - for (totalNumStones = 0, layerNum = 0; totalNumStones <= 18; totalNumStones++) - { - for (a = 0; a <= totalNumStones; a++) - { - for (b = 0; b <= totalNumStones - a; b++) - { - if (a > NUM_STONES_PER_PLAYER) - continue; - if (b > NUM_STONES_PER_PLAYER) - continue; - if (a + b != totalNumStones) - continue; + // moving phase + for (totalNumStones = 0, layerNum = 0; totalNumStones <= 18; totalNumStones++) { + for (a = 0; a <= totalNumStones; a++) { + for (b = 0; b <= totalNumStones - a; b++) { + if (a > NUM_STONES_PER_PLAYER) + continue; + if (b > NUM_STONES_PER_PLAYER) + continue; + if (a + b != totalNumStones) + continue; - layerIndex[LAYER_INDEX_MOVING_PHASE][a][b] = layerNum; - layer[layerNum].numWhiteStones = a; - layer[layerNum].numBlackStones = b; - layer[layerNum].numSubLayers = 0; + layerIndex[LAYER_INDEX_MOVING_PHASE][a][b] = layerNum; + layer[layerNum].numWhiteStones = a; + layer[layerNum].numBlackStones = b; + layer[layerNum].numSubLayers = 0; - for (wCD = 0; wCD <= layer[layerNum].numWhiteStones; wCD++) - { - for (bCD = 0; bCD <= layer[layerNum].numBlackStones; bCD++) - { + for (wCD = 0; wCD <= layer[layerNum].numWhiteStones; wCD++) { + for (bCD = 0; bCD <= layer[layerNum].numBlackStones; bCD++) { - // calc number of white and black stones for group A&B - wAB = layer[layerNum].numWhiteStones - wCD; - bAB = layer[layerNum].numBlackStones - bCD; + // calc number of white and black stones for group A&B + wAB = layer[layerNum].numWhiteStones - wCD; + bAB = layer[layerNum].numBlackStones - bCD; - // conditions - if (wCD + wAB != layer[layerNum].numWhiteStones) - continue; - if (bCD + bAB != layer[layerNum].numBlackStones) - continue; - if (wAB + bAB > numSquaresGroupA + numSquaresGroupB) - continue; - if (wCD + bCD > numSquaresGroupC + numSquaresGroupD) - continue; + // conditions + if (wCD + wAB != layer[layerNum].numWhiteStones) + continue; + if (bCD + bAB != layer[layerNum].numBlackStones) + continue; + if (wAB + bAB > numSquaresGroupA + numSquaresGroupB) + continue; + if (wCD + bCD > numSquaresGroupC + numSquaresGroupD) + continue; - if (layer[layerNum].numSubLayers > 0) - { - layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD]; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; - } - else - { - layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD] - 1; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = 0; - } - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupAB = bAB; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupCD = bCD; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupAB = wAB; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupCD = wCD; - layer[layerNum].subLayerIndexAB[wAB][bAB] = layer[layerNum].numSubLayers; - layer[layerNum].subLayerIndexCD[wCD][bCD] = layer[layerNum].numSubLayers; - layer[layerNum].numSubLayers++; - } - } - layerNum++; - } - } - } + if (layer[layerNum].numSubLayers > 0) { + layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD]; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; + } else { + layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD] - 1; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = 0; + } + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupAB = bAB; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupCD = bCD; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupAB = wAB; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupCD = wCD; + layer[layerNum].subLayerIndexAB[wAB][bAB] = layer[layerNum].numSubLayers; + layer[layerNum].subLayerIndexCD[wCD][bCD] = layer[layerNum].numSubLayers; + layer[layerNum].numSubLayers++; + } + } + layerNum++; + } + } + } - // setting phase - for (totalNumStones = 0, layerNum = NUM_LAYERS - 1; totalNumStones <= 2 * NUM_STONES_PER_PLAYER; totalNumStones++) - { - for (a = 0; a <= totalNumStones; a++) - { - for (b = 0; b <= totalNumStones - a; b++) - { - if (a > NUM_STONES_PER_PLAYER) - continue; - if (b > NUM_STONES_PER_PLAYER) - continue; - if (a + b != totalNumStones) - continue; - layer[layerNum].numWhiteStones = a; - layer[layerNum].numBlackStones = b; - layerIndex[LAYER_INDEX_SETTING_PHASE][a][b] = layerNum; - layer[layerNum].numSubLayers = 0; + // setting phase + for (totalNumStones = 0, layerNum = NUM_LAYERS - 1; totalNumStones <= 2 * NUM_STONES_PER_PLAYER; totalNumStones++) { + for (a = 0; a <= totalNumStones; a++) { + for (b = 0; b <= totalNumStones - a; b++) { + if (a > NUM_STONES_PER_PLAYER) + continue; + if (b > NUM_STONES_PER_PLAYER) + continue; + if (a + b != totalNumStones) + continue; + layer[layerNum].numWhiteStones = a; + layer[layerNum].numBlackStones = b; + layerIndex[LAYER_INDEX_SETTING_PHASE][a][b] = layerNum; + layer[layerNum].numSubLayers = 0; - for (wCD = 0; wCD <= layer[layerNum].numWhiteStones; wCD++) - { - for (bCD = 0; bCD <= layer[layerNum].numBlackStones; bCD++) - { + for (wCD = 0; wCD <= layer[layerNum].numWhiteStones; wCD++) { + for (bCD = 0; bCD <= layer[layerNum].numBlackStones; bCD++) { - // calc number of white and black stones for group A&B - wAB = layer[layerNum].numWhiteStones - wCD; - bAB = layer[layerNum].numBlackStones - bCD; + // calc number of white and black stones for group A&B + wAB = layer[layerNum].numWhiteStones - wCD; + bAB = layer[layerNum].numBlackStones - bCD; - // conditions - if (wCD + wAB != layer[layerNum].numWhiteStones) - continue; - if (bCD + bAB != layer[layerNum].numBlackStones) - continue; - if (wAB + bAB > numSquaresGroupA + numSquaresGroupB) - continue; - if (wCD + bCD > numSquaresGroupC + numSquaresGroupD) - continue; + // conditions + if (wCD + wAB != layer[layerNum].numWhiteStones) + continue; + if (bCD + bAB != layer[layerNum].numBlackStones) + continue; + if (wAB + bAB > numSquaresGroupA + numSquaresGroupB) + continue; + if (wCD + bCD > numSquaresGroupC + numSquaresGroupD) + continue; - if (layer[layerNum].numSubLayers > 0) - { - layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD]; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; - } - else - { - layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD] - 1; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = 0; - } - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupAB = bAB; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupCD = bCD; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupAB = wAB; - layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupCD = wCD; - layer[layerNum].subLayerIndexAB[wAB][bAB] = layer[layerNum].numSubLayers; - layer[layerNum].subLayerIndexCD[wCD][bCD] = layer[layerNum].numSubLayers; - layer[layerNum].numSubLayers++; - } - } - layerNum--; - } - } - } + if (layer[layerNum].numSubLayers > 0) { + layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD]; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; + } else { + layer[layerNum].subLayer[layer[layerNum].numSubLayers].maxIndex = anzahlStellungenAB[wAB][bAB] * anzahlStellungenCD[wCD][bCD] - 1; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].minIndex = 0; + } + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupAB = bAB; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numBlackStonesGroupCD = bCD; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupAB = wAB; + layer[layerNum].subLayer[layer[layerNum].numSubLayers].numWhiteStonesGroupCD = wCD; + layer[layerNum].subLayerIndexAB[wAB][bAB] = layer[layerNum].numSubLayers; + layer[layerNum].subLayerIndexCD[wCD][bCD] = layer[layerNum].numSubLayers; + layer[layerNum].numSubLayers++; + } + } + layerNum--; + } + } + } - // write vars into file - preCalcVarsHeader.sizeInBytes = sizeof(PreCalcedVarsFileHeader); + // write vars into file + preCalcVarsHeader.sizeInBytes = sizeof(PreCalcedVarsFileHeader); - WriteFile(hFilePreCalcVars, &preCalcVarsHeader, preCalcVarsHeader.sizeInBytes, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, layer, sizeof(Layer) * NUM_LAYERS, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, layerIndex, sizeof(unsigned int) * 2 * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, anzahlStellungenAB, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, anzahlStellungenCD, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, indexAB, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, indexCD, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, symmetryOperationCD, sizeof(unsigned char) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, powerOfThree, sizeof(unsigned int) * (numSquaresGroupC + numSquaresGroupD), &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, symmetryOperationTable, sizeof(unsigned int) * fieldStruct::size * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, reverseSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, concSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, mOverN, sizeof(unsigned int) * (fieldStruct::size + 1) * (fieldStruct::size + 1), &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); - WriteFile(hFilePreCalcVars, incidencesValuesSubMoves, sizeof(unsigned int) * 4 * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, &preCalcVarsHeader, preCalcVarsHeader.sizeInBytes, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, layer, sizeof(Layer) * NUM_LAYERS, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, layerIndex, sizeof(unsigned int) * 2 * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, anzahlStellungenAB, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, anzahlStellungenCD, sizeof(unsigned int) * NUM_STONES_PER_PLAYER_PLUS_ONE * NUM_STONES_PER_PLAYER_PLUS_ONE, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, indexAB, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, indexCD, sizeof(unsigned int) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, symmetryOperationCD, sizeof(unsigned char) * MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, powerOfThree, sizeof(unsigned int) * (numSquaresGroupC + numSquaresGroupD), &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, symmetryOperationTable, sizeof(unsigned int) * fieldStruct::size * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, reverseSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, concSymOperation, sizeof(unsigned int) * NUM_SYM_OPERATIONS * NUM_SYM_OPERATIONS, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, mOverN, sizeof(unsigned int) * (fieldStruct::size + 1) * (fieldStruct::size + 1), &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); + WriteFile(hFilePreCalcVars, incidencesValuesSubMoves, sizeof(unsigned int) * 4 * fieldStruct::size * fieldStruct::size, &dwBytesWritten, nullptr); - // process originalStateAB[][] - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupA + numSquaresGroupB) - continue; - WriteFile(hFilePreCalcVars, originalStateAB[a][b], sizeof(unsigned int) * anzahlStellungenAB[a][b], &dwBytesWritten, nullptr); - } - } + // process originalStateAB[][] + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupA + numSquaresGroupB) + continue; + WriteFile(hFilePreCalcVars, originalStateAB[a][b], sizeof(unsigned int) * anzahlStellungenAB[a][b], &dwBytesWritten, nullptr); + } + } - // process originalStateCD[][] - for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) - { - for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) - { - if (a + b > numSquaresGroupC + numSquaresGroupD) - continue; - WriteFile(hFilePreCalcVars, originalStateCD[a][b], sizeof(unsigned int) * anzahlStellungenCD[a][b], &dwBytesWritten, nullptr); - } - } - } + // process originalStateCD[][] + for (a = 0; a <= NUM_STONES_PER_PLAYER; a++) { + for (b = 0; b <= NUM_STONES_PER_PLAYER; b++) { + if (a + b > numSquaresGroupC + numSquaresGroupD) + continue; + WriteFile(hFilePreCalcVars, originalStateCD[a][b], sizeof(unsigned int) * anzahlStellungenCD[a][b], &dwBytesWritten, nullptr); + } + } + } - // Close File - CloseHandle(hFilePreCalcVars); + // Close File + CloseHandle(hFilePreCalcVars); } //----------------------------------------------------------------------------- @@ -692,18 +641,17 @@ PerfectAI::PerfectAI(const char *directory) //----------------------------------------------------------------------------- PerfectAI::~PerfectAI() { - // locals - unsigned int curThread; + // locals + unsigned int curThread; - // release memory - for (curThread = 0; curThread < getNumThreads(); curThread++) - { - SAFE_DELETE_ARRAY(threadVars[curThread].oldStates); - SAFE_DELETE_ARRAY(threadVars[curThread].idPossibilities); - SAFE_DELETE_ARRAY(threadVars[curThread].possibilities); - threadVars[curThread].field->deleteBoard(); - } - SAFE_DELETE_ARRAY(threadVars); + // release memory + for (curThread = 0; curThread < getNumThreads(); curThread++) { + SAFE_DELETE_ARRAY(threadVars[curThread].oldStates); + SAFE_DELETE_ARRAY(threadVars[curThread].idPossibilities); + SAFE_DELETE_ARRAY(threadVars[curThread].possibilities); + threadVars[curThread].field->deleteBoard(); + } + SAFE_DELETE_ARRAY(threadVars); } //----------------------------------------------------------------------------- @@ -712,66 +660,57 @@ PerfectAI::~PerfectAI() //----------------------------------------------------------------------------- void PerfectAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo) { - // ... trick 17 - theField->copyBoard(&dummyField); + // ... trick 17 + theField->copyBoard(&dummyField); - // locals - threadVars[0].field = theField; - threadVars[0].ownId = threadVars[0].field->curPlayer->id; - unsigned int bestChoice, i; + // locals + threadVars[0].field = theField; + threadVars[0].ownId = threadVars[0].field->curPlayer->id; + unsigned int bestChoice, i; - // reset - for (i = 0; i < fieldStruct::size * fieldStruct::size; i++) - { - valueOfMove[i] = SKV_VALUE_INVALID; - plyInfoForOutput[i] = PLYINFO_VALUE_INVALID; - incidencesValuesSubMoves[i][SKV_VALUE_INVALID] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_LOST] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_DRAWN] = 0; - incidencesValuesSubMoves[i][SKV_VALUE_GAME_WON] = 0; - } + // reset + for (i = 0; i < fieldStruct::size * fieldStruct::size; i++) { + valueOfMove[i] = SKV_VALUE_INVALID; + plyInfoForOutput[i] = PLYINFO_VALUE_INVALID; + incidencesValuesSubMoves[i][SKV_VALUE_INVALID] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_LOST] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_DRAWN] = 0; + incidencesValuesSubMoves[i][SKV_VALUE_GAME_WON] = 0; + } - // open database file - openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES); + // open database file + openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES); - if (theField->settingPhase) - threadVars[0].depthOfFullTree = 2; - else - threadVars[0].depthOfFullTree = 2; + if (theField->settingPhase) + threadVars[0].depthOfFullTree = 2; + else + threadVars[0].depthOfFullTree = 2; - // current state already calculated? - if (isCurrentStateInDatabase(0)) - { - cout << "PerfectAI is using database!\n\n\n"; - threadVars[0].depthOfFullTree = 3; - } - else - { - cout << "PerfectAI is thinking thinking with a depth of " << threadVars[0].depthOfFullTree << " steps!\n\n\n"; - } + // current state already calculated? + if (isCurrentStateInDatabase(0)) { + cout << "PerfectAI is using database!\n\n\n"; + threadVars[0].depthOfFullTree = 3; + } else { + cout << "PerfectAI is thinking thinking with a depth of " << threadVars[0].depthOfFullTree << " steps!\n\n\n"; + } - // start the miniMax-algorithmn - Possibility *rootPossibilities = (Possibility *)getBestChoice(threadVars[0].depthOfFullTree, &bestChoice, MAX_NUM_POS_MOVES); + // start the miniMax-algorithmn + Possibility *rootPossibilities = (Possibility *)getBestChoice(threadVars[0].depthOfFullTree, &bestChoice, MAX_NUM_POS_MOVES); - // decode the best choice - if (threadVars[0].field->stoneMustBeRemoved) - { - *pushFrom = bestChoice; - *pushTo = 0; - } - else if (threadVars[0].field->settingPhase) - { - *pushFrom = 0; - *pushTo = bestChoice; - } - else - { - *pushFrom = rootPossibilities->from[bestChoice]; - *pushTo = rootPossibilities->to[bestChoice]; - } + // decode the best choice + if (threadVars[0].field->stoneMustBeRemoved) { + *pushFrom = bestChoice; + *pushTo = 0; + } else if (threadVars[0].field->settingPhase) { + *pushFrom = 0; + *pushTo = bestChoice; + } else { + *pushFrom = rootPossibilities->from[bestChoice]; + *pushTo = rootPossibilities->to[bestChoice]; + } - // release memory - threadVars[0].field = &dummyField; + // release memory + threadVars[0].field = &dummyField; } //----------------------------------------------------------------------------- @@ -780,19 +719,18 @@ void PerfectAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int //----------------------------------------------------------------------------- void PerfectAI::prepareDatabaseCalculation() { - // only prepare layers? - unsigned int curThread; + // only prepare layers? + unsigned int curThread; - // create a temporary board - for (curThread = 0; curThread < getNumThreads(); curThread++) - { - threadVars[curThread].field = new fieldStruct(); - threadVars[curThread].field->createBoard(); - setOpponentLevel(curThread, false); - } + // create a temporary board + for (curThread = 0; curThread < getNumThreads(); curThread++) { + threadVars[curThread].field = new fieldStruct(); + threadVars[curThread].field->createBoard(); + setOpponentLevel(curThread, false); + } - // open database file - openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES); + // open database file + openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES); } //----------------------------------------------------------------------------- @@ -801,16 +739,15 @@ void PerfectAI::prepareDatabaseCalculation() //----------------------------------------------------------------------------- void PerfectAI::wrapUpDatabaseCalculation(bool calculationAborted) { - // locals - unsigned int curThread; + // locals + unsigned int curThread; - // release memory - for (curThread = 0; curThread < getNumThreads(); curThread++) - { - threadVars[curThread].field->deleteBoard(); - SAFE_DELETE(threadVars[curThread].field); - threadVars[curThread].field = &dummyField; - } + // release memory + for (curThread = 0; curThread < getNumThreads(); curThread++) { + threadVars[curThread].field->deleteBoard(); + SAFE_DELETE(threadVars[curThread].field); + threadVars[curThread].field = &dummyField; + } } //----------------------------------------------------------------------------- @@ -819,24 +756,23 @@ void PerfectAI::wrapUpDatabaseCalculation(bool calculationAborted) //----------------------------------------------------------------------------- bool PerfectAI::testLayers(unsigned int startTestFromLayer, unsigned int endTestAtLayer) { - // locals - unsigned int curLayer; - bool result = true; + // locals + unsigned int curLayer; + bool result = true; - for (curLayer = startTestFromLayer; curLayer <= endTestAtLayer; curLayer++) - { - closeDatabase(); - if (!openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES)) - result = false; - if (!testIfSymStatesHaveSameValue(curLayer)) - result = false; - if (!testLayer(curLayer)) - result = false; - unloadAllLayers(); - unloadAllPlyInfos(); - closeDatabase(); - } - return result; + for (curLayer = startTestFromLayer; curLayer <= endTestAtLayer; curLayer++) { + closeDatabase(); + if (!openDatabase(databaseDirectory.c_str(), MAX_NUM_POS_MOVES)) + result = false; + if (!testIfSymStatesHaveSameValue(curLayer)) + result = false; + if (!testLayer(curLayer)) + result = false; + unloadAllLayers(); + unloadAllPlyInfos(); + closeDatabase(); + } + return result; } //----------------------------------------------------------------------------- @@ -845,16 +781,13 @@ bool PerfectAI::testLayers(unsigned int startTestFromLayer, unsigned int endTest //----------------------------------------------------------------------------- bool PerfectAI::setDatabasePath(const char *directory) { - if (directory == nullptr) - { - return false; - } - else - { - cout << "Path to database set to: " << directory << endl; - databaseDirectory.assign(directory); - return true; - } + if (directory == nullptr) { + return false; + } else { + cout << "Path to database set to: " << directory << endl; + databaseDirectory.assign(directory); + return true; + } } //----------------------------------------------------------------------------- @@ -863,13 +796,12 @@ bool PerfectAI::setDatabasePath(const char *directory) //----------------------------------------------------------------------------- void PerfectAI::prepareBestChoiceCalculation() { - for (unsigned int curThread = 0; curThread < getNumThreads(); curThread++) - { - threadVars[curThread].floatValue = 0.0f; - threadVars[curThread].shortValue = SKV_VALUE_INVALID; - threadVars[curThread].gameHasFinished = false; - threadVars[curThread].curSearchDepth = 0; - } + for (unsigned int curThread = 0; curThread < getNumThreads(); curThread++) { + threadVars[curThread].floatValue = 0.0f; + threadVars[curThread].shortValue = SKV_VALUE_INVALID; + threadVars[curThread].gameHasFinished = false; + threadVars[curThread].curSearchDepth = 0; + } } //----------------------------------------------------------------------------- @@ -878,17 +810,17 @@ void PerfectAI::prepareBestChoiceCalculation() //----------------------------------------------------------------------------- PerfectAI::ThreadVars::ThreadVars() { - field = nullptr; - floatValue = 0; - shortValue = 0; - gameHasFinished = false; - ownId = 0; - curSearchDepth = 0; - depthOfFullTree = 0; - idPossibilities = nullptr; - oldStates = nullptr; - possibilities = nullptr; - parent = nullptr; + field = nullptr; + floatValue = 0; + shortValue = 0; + gameHasFinished = false; + ownId = 0; + curSearchDepth = 0; + depthOfFullTree = 0; + idPossibilities = nullptr; + oldStates = nullptr; + possibilities = nullptr; + parent = nullptr; } //----------------------------------------------------------------------------- @@ -897,52 +829,47 @@ PerfectAI::ThreadVars::ThreadVars() //----------------------------------------------------------------------------- unsigned int *PerfectAI::ThreadVars::getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int i; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - bool stoneCanBeRemoved; - unsigned int numberOfMillsBeeingClosed; + // locals + unsigned int i; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + bool stoneCanBeRemoved; + unsigned int numberOfMillsBeeingClosed; - // check if an opponent stone can be removed - for (stoneCanBeRemoved = false, i = 0; i < field->size; i++) - { - if (field->board[i] == field->oppPlayer->id && field->stonePartOfMill[i] == 0) - { - stoneCanBeRemoved = true; - break; - } - } + // check if an opponent stone can be removed + for (stoneCanBeRemoved = false, i = 0; i < field->size; i++) { + if (field->board[i] == field->oppPlayer->id && field->stonePartOfMill[i] == 0) { + stoneCanBeRemoved = true; + break; + } + } - // possibilities with cut off - for ((*numPossibilities) = 0, i = 0; i < field->size; i++) - { + // possibilities with cut off + for ((*numPossibilities) = 0, i = 0; i < field->size; i++) { - // move possible ? - if (field->board[i] == field->squareIsFree) - { + // move possible ? + if (field->board[i] == field->squareIsFree) { - // check if a mill is beeing closed - numberOfMillsBeeingClosed = 0; - if (field->curPlayer->id == field->board[field->neighbour[i][0][0]] && field->curPlayer->id == field->board[field->neighbour[i][0][1]]) - numberOfMillsBeeingClosed++; - if (field->curPlayer->id == field->board[field->neighbour[i][1][0]] && field->curPlayer->id == field->board[field->neighbour[i][1][1]]) - numberOfMillsBeeingClosed++; + // check if a mill is beeing closed + numberOfMillsBeeingClosed = 0; + if (field->curPlayer->id == field->board[field->neighbour[i][0][0]] && field->curPlayer->id == field->board[field->neighbour[i][0][1]]) + numberOfMillsBeeingClosed++; + if (field->curPlayer->id == field->board[field->neighbour[i][1][0]] && field->curPlayer->id == field->board[field->neighbour[i][1][1]]) + numberOfMillsBeeingClosed++; - // Version 15: don't allow to close two mills at once - // Version 25: don't allow to close a mill, although no stone can be removed from the opponent - if ((numberOfMillsBeeingClosed < 2) && (numberOfMillsBeeingClosed == 0 || stoneCanBeRemoved)) - { - idPossibility[*numPossibilities] = i; - (*numPossibilities)++; - } - } - } + // Version 15: don't allow to close two mills at once + // Version 25: don't allow to close a mill, although no stone can be removed from the opponent + if ((numberOfMillsBeeingClosed < 2) && (numberOfMillsBeeingClosed == 0 || stoneCanBeRemoved)) { + idPossibility[*numPossibilities] = i; + (*numPossibilities)++; + } + } + } - // possibility code is simple - if (pPossibilities != nullptr) - *pPossibilities = nullptr; + // possibility code is simple + if (pPossibilities != nullptr) + *pPossibilities = nullptr; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -951,69 +878,58 @@ unsigned int *PerfectAI::ThreadVars::getPossSettingPhase(unsigned int *numPossib //----------------------------------------------------------------------------- unsigned int *PerfectAI::ThreadVars::getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int from, to, dir; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - Possibility *possibility = &possibilities[curSearchDepth]; + // locals + unsigned int from, to, dir; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + Possibility *possibility = &possibilities[curSearchDepth]; - // if he is not allowed to spring - if (field->curPlayer->numStones > 3) - { + // if he is not allowed to spring + if (field->curPlayer->numStones > 3) { - for ((*numPossibilities) = 0, from = 0; from < field->size; from++) - { - for (dir = 0; dir < 4; dir++) - { + for ((*numPossibilities) = 0, from = 0; from < field->size; from++) { + for (dir = 0; dir < 4; dir++) { - // destination - to = field->connectedSquare[from][dir]; + // destination + to = field->connectedSquare[from][dir]; - // move possible ? - if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) - { + // move possible ? + if (to < field->size && field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree) { - // stone is moveable - idPossibility[*numPossibilities] = *numPossibilities; - possibility->from[*numPossibilities] = from; - possibility->to[*numPossibilities] = to; - (*numPossibilities)++; + // stone is moveable + idPossibility[*numPossibilities] = *numPossibilities; + possibility->from[*numPossibilities] = from; + possibility->to[*numPossibilities] = to; + (*numPossibilities)++; - // current player is allowed to spring - } - } - } - } - else if (field->curPlayer->numStones == 3) - { + // current player is allowed to spring + } + } + } + } else if (field->curPlayer->numStones == 3) { - for ((*numPossibilities) = 0, from = 0; from < field->size; from++) - { - for (to = 0; to < field->size; to++) - { + for ((*numPossibilities) = 0, from = 0; from < field->size; from++) { + for (to = 0; to < field->size; to++) { - // move possible ? - if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) - { + // move possible ? + if (field->board[from] == field->curPlayer->id && field->board[to] == field->squareIsFree && *numPossibilities < MAX_NUM_POS_MOVES) { - // stone is moveable - idPossibility[*numPossibilities] = *numPossibilities; - possibility->from[*numPossibilities] = from; - possibility->to[*numPossibilities] = to; - (*numPossibilities)++; - } - } - } - } - else - { - *numPossibilities = 0; - } + // stone is moveable + idPossibility[*numPossibilities] = *numPossibilities; + possibility->from[*numPossibilities] = from; + possibility->to[*numPossibilities] = to; + (*numPossibilities)++; + } + } + } + } else { + *numPossibilities = 0; + } - // pass possibilities - if (pPossibilities != nullptr) - *pPossibilities = (void *)possibility; + // pass possibilities + if (pPossibilities != nullptr) + *pPossibilities = (void *)possibility; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -1022,28 +938,26 @@ unsigned int *PerfectAI::ThreadVars::getPossNormalMove(unsigned int *numPossibil //----------------------------------------------------------------------------- unsigned int *PerfectAI::ThreadVars::getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities) { - // locals - unsigned int i; - unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; + // locals + unsigned int i; + unsigned int *idPossibility = &idPossibilities[curSearchDepth * MAX_NUM_POS_MOVES]; - // possibilities with cut off - for ((*numPossibilities) = 0, i = 0; i < field->size; i++) - { + // possibilities with cut off + for ((*numPossibilities) = 0, i = 0; i < field->size; i++) { - // move possible ? - if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) - { + // move possible ? + if (field->board[i] == field->oppPlayer->id && !field->stonePartOfMill[i]) { - idPossibility[*numPossibilities] = i; - (*numPossibilities)++; - } - } + idPossibility[*numPossibilities] = i; + (*numPossibilities)++; + } + } - // possibility code is simple - if (pPossibilities != nullptr) - *pPossibilities = nullptr; + // possibility code is simple + if (pPossibilities != nullptr) + *pPossibilities = nullptr; - return idPossibility; + return idPossibility; } //----------------------------------------------------------------------------- @@ -1052,45 +966,41 @@ unsigned int *PerfectAI::ThreadVars::getPossStoneRemove(unsigned int *numPossibi //----------------------------------------------------------------------------- unsigned int *PerfectAI::getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities) { - // locals - bool aStoneCanBeRemovedFromCurPlayer = 0; - unsigned int numberOfMillsCurrentPlayer = 0; - unsigned int numberOfMillsOpponentPlayer = 0; - unsigned int i; + // locals + bool aStoneCanBeRemovedFromCurPlayer = 0; + unsigned int numberOfMillsCurrentPlayer = 0; + unsigned int numberOfMillsOpponentPlayer = 0; + unsigned int i; - // set opponentsMove - ThreadVars *tv = &threadVars[threadNo]; - *opponentsMove = (tv->field->curPlayer->id == tv->ownId) ? false : true; + // set opponentsMove + ThreadVars *tv = &threadVars[threadNo]; + *opponentsMove = (tv->field->curPlayer->id == tv->ownId) ? false : true; - // count completed mills - for (i = 0; i < fieldStruct::size; i++) - { - if (tv->field->board[i] == tv->field->curPlayer->id) - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; - else - numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; - if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) - aStoneCanBeRemovedFromCurPlayer = true; - } - numberOfMillsCurrentPlayer /= 3; - numberOfMillsOpponentPlayer /= 3; + // count completed mills + for (i = 0; i < fieldStruct::size; i++) { + if (tv->field->board[i] == tv->field->curPlayer->id) + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; + else + numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; + if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) + aStoneCanBeRemovedFromCurPlayer = true; + } + numberOfMillsCurrentPlayer /= 3; + numberOfMillsOpponentPlayer /= 3; - // When game has ended of course nothing happens any more - if (tv->gameHasFinished || !tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer)) - { - *numPossibilities = 0; - return 0; - // look what is to do - } - else - { - if (tv->field->stoneMustBeRemoved) - return tv->getPossStoneRemove(numPossibilities, pPossibilities); - else if (tv->field->settingPhase) - return tv->getPossSettingPhase(numPossibilities, pPossibilities); - else - return tv->getPossNormalMove(numPossibilities, pPossibilities); - } + // When game has ended of course nothing happens any more + if (tv->gameHasFinished || !tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer)) { + *numPossibilities = 0; + return 0; + // look what is to do + } else { + if (tv->field->stoneMustBeRemoved) + return tv->getPossStoneRemove(numPossibilities, pPossibilities); + else if (tv->field->settingPhase) + return tv->getPossSettingPhase(numPossibilities, pPossibilities); + else + return tv->getPossNormalMove(numPossibilities, pPossibilities); + } } //----------------------------------------------------------------------------- @@ -1099,9 +1009,9 @@ unsigned int *PerfectAI::getPossibilities(unsigned int threadNo, unsigned int *n //----------------------------------------------------------------------------- void PerfectAI::getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue) { - ThreadVars *tv = &threadVars[threadNo]; - floatValue = tv->floatValue; - shortValue = tv->shortValue; + ThreadVars *tv = &threadVars[threadNo]; + floatValue = tv->floatValue; + shortValue = tv->shortValue; } //----------------------------------------------------------------------------- @@ -1118,35 +1028,34 @@ void PerfectAI::deletePossibilities(unsigned int threadNo, void *pPossibilities) //----------------------------------------------------------------------------- void PerfectAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities) { - // locals - ThreadVars *tv = &threadVars[threadNo]; - Backup *oldState = (Backup *)pBackup; + // locals + ThreadVars *tv = &threadVars[threadNo]; + Backup *oldState = (Backup *)pBackup; - // reset old value - tv->floatValue = oldState->floatValue; - tv->shortValue = oldState->shortValue; - tv->gameHasFinished = oldState->gameHasFinished; - tv->curSearchDepth--; + // reset old value + tv->floatValue = oldState->floatValue; + tv->shortValue = oldState->shortValue; + tv->gameHasFinished = oldState->gameHasFinished; + tv->curSearchDepth--; - tv->field->curPlayer = oldState->curPlayer; - tv->field->oppPlayer = oldState->oppPlayer; - tv->field->curPlayer->numStones = oldState->curNumStones; - tv->field->oppPlayer->numStones = oldState->oppNumStones; - tv->field->curPlayer->numStonesMissing = oldState->curMissStones; - tv->field->oppPlayer->numStonesMissing = oldState->oppMissStones; - tv->field->curPlayer->numPossibleMoves = oldState->curPosMoves; - tv->field->oppPlayer->numPossibleMoves = oldState->oppPosMoves; - tv->field->settingPhase = oldState->settingPhase; - tv->field->stonesSet = oldState->stonesSet; - tv->field->stoneMustBeRemoved = oldState->stoneMustBeRemoved; - tv->field->board[oldState->from] = oldState->fieldFrom; - tv->field->board[oldState->to] = oldState->fieldTo; + tv->field->curPlayer = oldState->curPlayer; + tv->field->oppPlayer = oldState->oppPlayer; + tv->field->curPlayer->numStones = oldState->curNumStones; + tv->field->oppPlayer->numStones = oldState->oppNumStones; + tv->field->curPlayer->numStonesMissing = oldState->curMissStones; + tv->field->oppPlayer->numStonesMissing = oldState->oppMissStones; + tv->field->curPlayer->numPossibleMoves = oldState->curPosMoves; + tv->field->oppPlayer->numPossibleMoves = oldState->oppPosMoves; + tv->field->settingPhase = oldState->settingPhase; + tv->field->stonesSet = oldState->stonesSet; + tv->field->stoneMustBeRemoved = oldState->stoneMustBeRemoved; + tv->field->board[oldState->from] = oldState->fieldFrom; + tv->field->board[oldState->to] = oldState->fieldTo; - // very expensive - for (int i = 0; i < tv->field->size; i++) - { - tv->field->stonePartOfMill[i] = oldState->stonePartOfMill[i]; - } + // very expensive + for (int i = 0; i < tv->field->size; i++) { + tv->field->stonePartOfMill[i] = oldState->stonePartOfMill[i]; + } } //----------------------------------------------------------------------------- @@ -1155,22 +1064,20 @@ void PerfectAI::undo(unsigned int threadNo, unsigned int idPossibility, bool opp //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::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 (field->board[stoneOne] == field->curPlayer->id && field->board[stoneTwo] == field->curPlayer->id && field->board[stoneThree] == field->curPlayer->id) - { - field->stonePartOfMill[stoneOne]++; - field->stonePartOfMill[stoneTwo]++; - field->stonePartOfMill[stoneThree]++; - field->stoneMustBeRemoved = 1; - } + // 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) { + field->stonePartOfMill[stoneOne]++; + field->stonePartOfMill[stoneTwo]++; + field->stonePartOfMill[stoneThree]++; + field->stoneMustBeRemoved = 1; + } - // is a mill destroyed ? - if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) - { - field->stonePartOfMill[stoneOne]--; - field->stonePartOfMill[stoneTwo]--; - field->stonePartOfMill[stoneThree]--; - } + // is a mill destroyed ? + if (field->board[stoneOne] == field->squareIsFree && field->stonePartOfMill[stoneOne] && field->stonePartOfMill[stoneTwo] && field->stonePartOfMill[stoneThree]) { + field->stonePartOfMill[stoneOne]--; + field->stonePartOfMill[stoneTwo]--; + field->stonePartOfMill[stoneThree]--; + } } //----------------------------------------------------------------------------- @@ -1179,29 +1086,28 @@ inline void PerfectAI::ThreadVars::setWarning(unsigned int stoneOne, unsigned in //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::updateWarning(unsigned int firstStone, unsigned int secondStone) { - // set warnings - if (firstStone < field->size) - this->setWarning(firstStone, field->neighbour[firstStone][0][0], field->neighbour[firstStone][0][1]); - if (firstStone < field->size) - this->setWarning(firstStone, field->neighbour[firstStone][1][0], field->neighbour[firstStone][1][1]); + // set warnings + if (firstStone < field->size) + this->setWarning(firstStone, field->neighbour[firstStone][0][0], field->neighbour[firstStone][0][1]); + if (firstStone < field->size) + this->setWarning(firstStone, field->neighbour[firstStone][1][0], field->neighbour[firstStone][1][1]); - if (secondStone < field->size) - this->setWarning(secondStone, field->neighbour[secondStone][0][0], field->neighbour[secondStone][0][1]); - if (secondStone < field->size) - this->setWarning(secondStone, field->neighbour[secondStone][1][0], field->neighbour[secondStone][1][1]); + if (secondStone < field->size) + this->setWarning(secondStone, field->neighbour[secondStone][0][0], field->neighbour[secondStone][0][1]); + if (secondStone < field->size) + this->setWarning(secondStone, field->neighbour[secondStone][1][0], field->neighbour[secondStone][1][1]); - // no stone must be removed if each belongs to a mill - unsigned int i; - bool atLeastOneStoneRemoveAble = false; - if (field->stoneMustBeRemoved) - for (i = 0; i < field->size; i++) - if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) - { - atLeastOneStoneRemoveAble = true; - break; - } - if (!atLeastOneStoneRemoveAble) - field->stoneMustBeRemoved = 0; + // no stone must be removed if each belongs to a mill + unsigned int i; + bool atLeastOneStoneRemoveAble = false; + if (field->stoneMustBeRemoved) + for (i = 0; i < field->size; i++) + if (field->stonePartOfMill[i] == 0 && field->board[i] == field->oppPlayer->id) { + atLeastOneStoneRemoveAble = true; + break; + } + if (!atLeastOneStoneRemoveAble) + field->stoneMustBeRemoved = 0; } //----------------------------------------------------------------------------- @@ -1210,58 +1116,51 @@ inline void PerfectAI::ThreadVars::updateWarning(unsigned int firstStone, unsign //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone) { - // locals - unsigned int neighbor, direction; + // locals + unsigned int neighbor, direction; - // look into every direction - for (direction = 0; direction < 4; direction++) - { + // look into every direction + for (direction = 0; direction < 4; direction++) { - neighbor = field->connectedSquare[stone][direction]; + neighbor = field->connectedSquare[stone][direction]; - // neighbor must exist - if (neighbor < field->size) - { + // neighbor must exist + if (neighbor < field->size) { - // relevant when moving from one square to another connected square - if (ignoreStone == neighbor) - continue; + // relevant when moving from one square to another connected square + if (ignoreStone == neighbor) + continue; - // if there is no neighbour stone than it only affects the actual stone - if (field->board[neighbor] == field->squareIsFree) - { + // if there is no neighbour stone than it only affects the actual stone + if (field->board[neighbor] == field->squareIsFree) { - if (stoneRemoved) - stoneOwner->numPossibleMoves--; - else - stoneOwner->numPossibleMoves++; + if (stoneRemoved) + stoneOwner->numPossibleMoves--; + else + stoneOwner->numPossibleMoves++; - // if there is a neighbour stone than it effects only this one - } - else if (field->board[neighbor] == field->curPlayer->id) - { + // if there is a neighbour stone than it effects only this one + } else if (field->board[neighbor] == field->curPlayer->id) { - if (stoneRemoved) - field->curPlayer->numPossibleMoves++; - else - field->curPlayer->numPossibleMoves--; - } - else - { + if (stoneRemoved) + field->curPlayer->numPossibleMoves++; + else + field->curPlayer->numPossibleMoves--; + } else { - if (stoneRemoved) - field->oppPlayer->numPossibleMoves++; - else - field->oppPlayer->numPossibleMoves--; - } - } - } + if (stoneRemoved) + field->oppPlayer->numPossibleMoves++; + else + field->oppPlayer->numPossibleMoves--; + } + } + } - // only 3 stones resting - if (field->curPlayer->numStones <= 3 && !field->settingPhase) - field->curPlayer->numPossibleMoves = field->curPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); - if (field->oppPlayer->numStones <= 3 && !field->settingPhase) - field->oppPlayer->numPossibleMoves = field->oppPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); + // only 3 stones resting + if (field->curPlayer->numStones <= 3 && !field->settingPhase) + field->curPlayer->numPossibleMoves = field->curPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); + if (field->oppPlayer->numStones <= 3 && !field->settingPhase) + field->oppPlayer->numPossibleMoves = field->oppPlayer->numStones * (field->size - field->curPlayer->numStones - field->oppPlayer->numStones); } //----------------------------------------------------------------------------- @@ -1270,26 +1169,26 @@ inline void PerfectAI::ThreadVars::updatePossibleMoves(unsigned int stone, Playe //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::setStone(unsigned int to, Backup *backup) { - // backup - backup->from = field->size; - backup->to = to; - backup->fieldFrom = field->size; - backup->fieldTo = field->board[to]; + // backup + backup->from = field->size; + backup->to = to; + backup->fieldFrom = field->size; + backup->fieldTo = field->board[to]; - // set stone into board - field->board[to] = field->curPlayer->id; - field->curPlayer->numStones++; - field->stonesSet++; + // set stone into board + field->board[to] = field->curPlayer->id; + field->curPlayer->numStones++; + field->stonesSet++; - // setting phase finished ? - if (field->stonesSet == 18) - field->settingPhase = false; + // setting phase finished ? + if (field->stonesSet == 18) + field->settingPhase = false; - // update possible moves - updatePossibleMoves(to, field->curPlayer, false, field->size); + // update possible moves + updatePossibleMoves(to, field->curPlayer, false, field->size); - // update warnings - updateWarning(to, field->size); + // update warnings + updateWarning(to, field->size); } //----------------------------------------------------------------------------- @@ -1298,22 +1197,22 @@ inline void PerfectAI::ThreadVars::setStone(unsigned int to, Backup *backup) //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::normalMove(unsigned int from, unsigned int to, Backup *backup) { - // backup - backup->from = from; - backup->to = to; - backup->fieldFrom = field->board[from]; - backup->fieldTo = field->board[to]; + // backup + backup->from = from; + backup->to = to; + backup->fieldFrom = field->board[from]; + backup->fieldTo = field->board[to]; - // set stone into board - field->board[from] = field->squareIsFree; - field->board[to] = field->curPlayer->id; + // set stone into board + field->board[from] = field->squareIsFree; + field->board[to] = field->curPlayer->id; - // update possible moves - updatePossibleMoves(from, field->curPlayer, true, to); - updatePossibleMoves(to, field->curPlayer, false, from); + // update possible moves + updatePossibleMoves(from, field->curPlayer, true, to); + updatePossibleMoves(to, field->curPlayer, false, from); - // update warnings - updateWarning(from, to); + // update warnings + updateWarning(from, to); } //----------------------------------------------------------------------------- @@ -1322,27 +1221,27 @@ inline void PerfectAI::ThreadVars::normalMove(unsigned int from, unsigned int to //----------------------------------------------------------------------------- inline void PerfectAI::ThreadVars::removeStone(unsigned int from, Backup *backup) { - // backup - backup->from = from; - backup->to = field->size; - backup->fieldFrom = field->board[from]; - backup->fieldTo = field->size; + // backup + backup->from = from; + backup->to = field->size; + backup->fieldFrom = field->board[from]; + backup->fieldTo = field->size; - // remove stone - field->board[from] = field->squareIsFree; - field->oppPlayer->numStones--; - field->oppPlayer->numStonesMissing++; - field->stoneMustBeRemoved--; + // remove stone + field->board[from] = field->squareIsFree; + field->oppPlayer->numStones--; + field->oppPlayer->numStonesMissing++; + field->stoneMustBeRemoved--; - // update possible moves - updatePossibleMoves(from, field->oppPlayer, true, field->size); + // update possible moves + updatePossibleMoves(from, field->oppPlayer, true, field->size); - // update warnings - updateWarning(from, field->size); + // update warnings + updateWarning(from, field->size); - // end of game ? - if ((field->oppPlayer->numStones < 3) && (!field->settingPhase)) - gameHasFinished = true; + // end of game ? + if ((field->oppPlayer->numStones < 3) && (!field->settingPhase)) + gameHasFinished = true; } //----------------------------------------------------------------------------- @@ -1351,82 +1250,75 @@ inline void PerfectAI::ThreadVars::removeStone(unsigned int from, Backup *backup //----------------------------------------------------------------------------- void PerfectAI::move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities) { - // locals - ThreadVars *tv = &threadVars[threadNo]; - Backup *oldState = &tv->oldStates[tv->curSearchDepth]; - Possibility *tmpPossibility = (Possibility *)pPossibilities; - Player *tmpPlayer; - unsigned int i; + // locals + ThreadVars *tv = &threadVars[threadNo]; + Backup *oldState = &tv->oldStates[tv->curSearchDepth]; + Possibility *tmpPossibility = (Possibility *)pPossibilities; + Player *tmpPlayer; + unsigned int i; - // calculate place of stone - *pBackup = (void *)oldState; - oldState->floatValue = tv->floatValue; - oldState->shortValue = tv->shortValue; - oldState->gameHasFinished = tv->gameHasFinished; - oldState->curPlayer = tv->field->curPlayer; - oldState->oppPlayer = tv->field->oppPlayer; - oldState->curNumStones = tv->field->curPlayer->numStones; - oldState->oppNumStones = tv->field->oppPlayer->numStones; - oldState->curPosMoves = tv->field->curPlayer->numPossibleMoves; - oldState->oppPosMoves = tv->field->oppPlayer->numPossibleMoves; - oldState->curMissStones = tv->field->curPlayer->numStonesMissing; - oldState->oppMissStones = tv->field->oppPlayer->numStonesMissing; - oldState->settingPhase = tv->field->settingPhase; - oldState->stonesSet = tv->field->stonesSet; - oldState->stoneMustBeRemoved = tv->field->stoneMustBeRemoved; - tv->curSearchDepth++; + // calculate place of stone + *pBackup = (void *)oldState; + oldState->floatValue = tv->floatValue; + oldState->shortValue = tv->shortValue; + oldState->gameHasFinished = tv->gameHasFinished; + oldState->curPlayer = tv->field->curPlayer; + oldState->oppPlayer = tv->field->oppPlayer; + oldState->curNumStones = tv->field->curPlayer->numStones; + oldState->oppNumStones = tv->field->oppPlayer->numStones; + oldState->curPosMoves = tv->field->curPlayer->numPossibleMoves; + oldState->oppPosMoves = tv->field->oppPlayer->numPossibleMoves; + oldState->curMissStones = tv->field->curPlayer->numStonesMissing; + oldState->oppMissStones = tv->field->oppPlayer->numStonesMissing; + oldState->settingPhase = tv->field->settingPhase; + oldState->stonesSet = tv->field->stonesSet; + oldState->stoneMustBeRemoved = tv->field->stoneMustBeRemoved; + tv->curSearchDepth++; - // very expensive - for (i = 0; i < tv->field->size; i++) - { - oldState->stonePartOfMill[i] = tv->field->stonePartOfMill[i]; - } + // very expensive + for (i = 0; i < tv->field->size; i++) { + oldState->stonePartOfMill[i] = tv->field->stonePartOfMill[i]; + } - // move - if (tv->field->stoneMustBeRemoved) - { - tv->removeStone(idPossibility, oldState); - } - else if (tv->field->settingPhase) - { - tv->setStone(idPossibility, oldState); - } - else - { - tv->normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState); - } + // move + if (tv->field->stoneMustBeRemoved) { + tv->removeStone(idPossibility, oldState); + } else if (tv->field->settingPhase) { + tv->setStone(idPossibility, oldState); + } else { + tv->normalMove(tmpPossibility->from[idPossibility], tmpPossibility->to[idPossibility], oldState); + } - // when opponent is unable to move than current player has won - if ((!tv->field->oppPlayer->numPossibleMoves) && (!tv->field->settingPhase) && (!tv->field->stoneMustBeRemoved) && (tv->field->oppPlayer->numStones > 3)) - tv->gameHasFinished = true; + // when opponent is unable to move than current player has won + if ((!tv->field->oppPlayer->numPossibleMoves) && (!tv->field->settingPhase) && (!tv->field->stoneMustBeRemoved) && (tv->field->oppPlayer->numStones > 3)) + tv->gameHasFinished = true; - // when game has finished - perfect for the current player - if (tv->gameHasFinished && !opponentsMove) - tv->shortValue = SKV_VALUE_GAME_WON; - if (tv->gameHasFinished && opponentsMove) - tv->shortValue = SKV_VALUE_GAME_LOST; + // when game has finished - perfect for the current player + if (tv->gameHasFinished && !opponentsMove) + tv->shortValue = SKV_VALUE_GAME_WON; + if (tv->gameHasFinished && opponentsMove) + tv->shortValue = SKV_VALUE_GAME_LOST; - tv->floatValue = tv->shortValue; + tv->floatValue = tv->shortValue; - // calc value - if (!opponentsMove) - tv->floatValue = (float)tv->field->oppPlayer->numStonesMissing - tv->field->curPlayer->numStonesMissing + tv->field->stoneMustBeRemoved + tv->field->curPlayer->numPossibleMoves * 0.1f - tv->field->oppPlayer->numPossibleMoves * 0.1f; - else - tv->floatValue = (float)tv->field->curPlayer->numStonesMissing - tv->field->oppPlayer->numStonesMissing - tv->field->stoneMustBeRemoved + tv->field->oppPlayer->numPossibleMoves * 0.1f - tv->field->curPlayer->numPossibleMoves * 0.1f; + // calc value + if (!opponentsMove) + tv->floatValue = (float)tv->field->oppPlayer->numStonesMissing - tv->field->curPlayer->numStonesMissing + tv->field->stoneMustBeRemoved + tv->field->curPlayer->numPossibleMoves * 0.1f - tv->field->oppPlayer->numPossibleMoves * 0.1f; + else + tv->floatValue = (float)tv->field->curPlayer->numStonesMissing - tv->field->oppPlayer->numStonesMissing - tv->field->stoneMustBeRemoved + tv->field->oppPlayer->numPossibleMoves * 0.1f - tv->field->curPlayer->numPossibleMoves * 0.1f; - // when game has finished - perfect for the current player - if (tv->gameHasFinished && !opponentsMove) - tv->floatValue = VALUE_GAME_WON - tv->curSearchDepth; - if (tv->gameHasFinished && opponentsMove) - tv->floatValue = VALUE_GAME_LOST + tv->curSearchDepth; + // when game has finished - perfect for the current player + if (tv->gameHasFinished && !opponentsMove) + tv->floatValue = VALUE_GAME_WON - tv->curSearchDepth; + if (tv->gameHasFinished && opponentsMove) + tv->floatValue = VALUE_GAME_LOST + tv->curSearchDepth; - // set next player - if (!tv->field->stoneMustBeRemoved) - { - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; - } + // set next player + if (!tv->field->stoneMustBeRemoved) { + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; + } } //----------------------------------------------------------------------------- @@ -1435,24 +1327,24 @@ void PerfectAI::move(unsigned int threadNo, unsigned int idPossibility, bool opp //----------------------------------------------------------------------------- void PerfectAI::storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, unsigned char value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo) { - // locals - ThreadVars *tv = &threadVars[threadNo]; - unsigned int index; - Possibility *tmpPossibility = (Possibility *)pPossibilities; + // locals + ThreadVars *tv = &threadVars[threadNo]; + unsigned int index; + Possibility *tmpPossibility = (Possibility *)pPossibilities; - if (tv->field->stoneMustBeRemoved) - index = idPossibility; - else if (tv->field->settingPhase) - index = idPossibility; - else - index = tmpPossibility->from[idPossibility] * fieldStruct::size + tmpPossibility->to[idPossibility]; + if (tv->field->stoneMustBeRemoved) + index = idPossibility; + else if (tv->field->settingPhase) + index = idPossibility; + else + index = tmpPossibility->from[idPossibility] * fieldStruct::size + tmpPossibility->to[idPossibility]; - plyInfoForOutput[index] = plyInfo; - valueOfMove[index] = value; - incidencesValuesSubMoves[index][SKV_VALUE_INVALID] = freqValuesSubMoves[SKV_VALUE_INVALID]; - incidencesValuesSubMoves[index][SKV_VALUE_GAME_LOST] = freqValuesSubMoves[SKV_VALUE_GAME_LOST]; - incidencesValuesSubMoves[index][SKV_VALUE_GAME_DRAWN] = freqValuesSubMoves[SKV_VALUE_GAME_DRAWN]; - incidencesValuesSubMoves[index][SKV_VALUE_GAME_WON] = freqValuesSubMoves[SKV_VALUE_GAME_WON]; + plyInfoForOutput[index] = plyInfo; + valueOfMove[index] = value; + incidencesValuesSubMoves[index][SKV_VALUE_INVALID] = freqValuesSubMoves[SKV_VALUE_INVALID]; + incidencesValuesSubMoves[index][SKV_VALUE_GAME_LOST] = freqValuesSubMoves[SKV_VALUE_GAME_LOST]; + incidencesValuesSubMoves[index][SKV_VALUE_GAME_DRAWN] = freqValuesSubMoves[SKV_VALUE_GAME_DRAWN]; + incidencesValuesSubMoves[index][SKV_VALUE_GAME_WON] = freqValuesSubMoves[SKV_VALUE_GAME_WON]; } //----------------------------------------------------------------------------- @@ -1461,112 +1353,83 @@ void PerfectAI::storeValueOfMove(unsigned int threadNo, unsigned int idPossibili //----------------------------------------------------------------------------- void PerfectAI::getValueOfMoves(unsigned char *moveValue, unsigned int *freqValuesSubMoves, PlyInfoVarType *plyInfo, unsigned int *moveQuality, unsigned char &knotValue, PlyInfoVarType &bestAmountOfPlies) { - // locals - unsigned int moveQualities[fieldStruct::size * fieldStruct::size]; // 0 is bad, 1 is good - unsigned int i, j; + // locals + unsigned int moveQualities[fieldStruct::size * fieldStruct::size]; // 0 is bad, 1 is good + unsigned int i, j; - // set an invalid default value - knotValue = SKV_NUM_VALUES; + // set an invalid default value + knotValue = SKV_NUM_VALUES; - // calc knotValue - for (i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { - if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_WON) - { - knotValue = SKV_VALUE_GAME_WON; - i = fieldStruct::size; - j = fieldStruct::size; - } - else if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_DRAWN) - { - knotValue = SKV_VALUE_GAME_DRAWN; - } - else if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_LOST && knotValue != SKV_VALUE_GAME_DRAWN) - { - knotValue = SKV_VALUE_GAME_LOST; - } - } - } + // calc knotValue + for (i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { + if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_WON) { + knotValue = SKV_VALUE_GAME_WON; + i = fieldStruct::size; + j = fieldStruct::size; + } else if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_DRAWN) { + knotValue = SKV_VALUE_GAME_DRAWN; + } else if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_LOST && knotValue != SKV_VALUE_GAME_DRAWN) { + knotValue = SKV_VALUE_GAME_LOST; + } + } + } - // calc move bestAmountOfPlies - if (knotValue == SKV_VALUE_GAME_WON) - { - bestAmountOfPlies = PLYINFO_VALUE_INVALID; + // calc move bestAmountOfPlies + if (knotValue == SKV_VALUE_GAME_WON) { + bestAmountOfPlies = PLYINFO_VALUE_INVALID; - for (i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { - if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_WON) - { - if (bestAmountOfPlies >= plyInfoForOutput[i * fieldStruct::size + j]) - { - bestAmountOfPlies = plyInfoForOutput[i * fieldStruct::size + j]; - } - } - } - } - } - else if (knotValue == SKV_VALUE_GAME_LOST) - { - bestAmountOfPlies = 0; + for (i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { + if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_WON) { + if (bestAmountOfPlies >= plyInfoForOutput[i * fieldStruct::size + j]) { + bestAmountOfPlies = plyInfoForOutput[i * fieldStruct::size + j]; + } + } + } + } + } else if (knotValue == SKV_VALUE_GAME_LOST) { + bestAmountOfPlies = 0; - for (i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { - if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_LOST) - { - if (bestAmountOfPlies <= plyInfoForOutput[i * fieldStruct::size + j]) - { - bestAmountOfPlies = plyInfoForOutput[i * fieldStruct::size + j]; - } - } - } - } - } - else if (knotValue == SKV_VALUE_GAME_DRAWN) - { - bestAmountOfPlies = 0; + for (i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { + if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_LOST) { + if (bestAmountOfPlies <= plyInfoForOutput[i * fieldStruct::size + j]) { + bestAmountOfPlies = plyInfoForOutput[i * fieldStruct::size + j]; + } + } + } + } + } else if (knotValue == SKV_VALUE_GAME_DRAWN) { + bestAmountOfPlies = 0; - for (i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { - if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_DRAWN) - { - if (bestAmountOfPlies <= incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON]) - { - bestAmountOfPlies = incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON]; - } - } - } - } - } + for (i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { + if (valueOfMove[i * fieldStruct::size + j] == SKV_VALUE_GAME_DRAWN) { + if (bestAmountOfPlies <= incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON]) { + bestAmountOfPlies = incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON]; + } + } + } + } + } - // zero move qualities - for (i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { - if ((valueOfMove[i * fieldStruct::size + j] == knotValue && bestAmountOfPlies == plyInfoForOutput[i * fieldStruct::size + j] && knotValue != SKV_VALUE_GAME_DRAWN) || (valueOfMove[i * fieldStruct::size + j] == knotValue && bestAmountOfPlies == incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON] && knotValue == SKV_VALUE_GAME_DRAWN)) - { - moveQualities[i * fieldStruct::size + j] = 1; - } - else - { - moveQualities[i * fieldStruct::size + j] = 0; - } - } - } + // zero move qualities + for (i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { + if ((valueOfMove[i * fieldStruct::size + j] == knotValue && bestAmountOfPlies == plyInfoForOutput[i * fieldStruct::size + j] && knotValue != SKV_VALUE_GAME_DRAWN) || (valueOfMove[i * fieldStruct::size + j] == knotValue && bestAmountOfPlies == incidencesValuesSubMoves[i * fieldStruct::size + j][SKV_VALUE_GAME_WON] && knotValue == SKV_VALUE_GAME_DRAWN)) { + moveQualities[i * fieldStruct::size + j] = 1; + } else { + moveQualities[i * fieldStruct::size + j] = 0; + } + } + } - // copy - memcpy(moveQuality, moveQualities, sizeof(unsigned int) * fieldStruct::size * fieldStruct::size); - memcpy(plyInfo, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size); - memcpy(moveValue, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size); - memcpy(freqValuesSubMoves, incidencesValuesSubMoves, sizeof(unsigned int) * fieldStruct::size * fieldStruct::size * 4); + // copy + memcpy(moveQuality, moveQualities, sizeof(unsigned int) * fieldStruct::size * fieldStruct::size); + memcpy(plyInfo, plyInfoForOutput, sizeof(PlyInfoVarType) * fieldStruct::size * fieldStruct::size); + memcpy(moveValue, valueOfMove, sizeof(unsigned char) * fieldStruct::size * fieldStruct::size); + memcpy(freqValuesSubMoves, incidencesValuesSubMoves, sizeof(unsigned int) * fieldStruct::size * fieldStruct::size * 4); } //----------------------------------------------------------------------------- @@ -1575,17 +1438,17 @@ void PerfectAI::getValueOfMoves(unsigned char *moveValue, unsigned int *freqValu //----------------------------------------------------------------------------- void PerfectAI::printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities) { - // locals - ThreadVars *tv = &threadVars[threadNo]; - Possibility *tmpPossibility = (Possibility *)pPossibilities; + // locals + ThreadVars *tv = &threadVars[threadNo]; + Possibility *tmpPossibility = (Possibility *)pPossibilities; - // move - if (tv->field->stoneMustBeRemoved) - cout << "remove stone from " << (char)(idPossibility + 97); - else if (tv->field->settingPhase) - cout << "set stone to " << (char)(idPossibility + 97); - else - cout << "move from " << (char)(tmpPossibility->from[idPossibility] + 97) << " to " << (char)(tmpPossibility->to[idPossibility] + 97); + // move + if (tv->field->stoneMustBeRemoved) + cout << "remove stone from " << (char)(idPossibility + 97); + else if (tv->field->settingPhase) + cout << "set stone to " << (char)(idPossibility + 97); + else + cout << "move from " << (char)(tmpPossibility->from[idPossibility] + 97) << " to " << (char)(tmpPossibility->to[idPossibility] + 97); } //----------------------------------------------------------------------------- @@ -1594,7 +1457,7 @@ void PerfectAI::printMoveInformation(unsigned int threadNo, unsigned int idPossi //----------------------------------------------------------------------------- unsigned int PerfectAI::getNumberOfLayers() { - return NUM_LAYERS; + return NUM_LAYERS; } //----------------------------------------------------------------------------- @@ -1603,10 +1466,10 @@ unsigned int PerfectAI::getNumberOfLayers() //----------------------------------------------------------------------------- bool PerfectAI::shallRetroAnalysisBeUsed(unsigned int layerNum) { - if (layerNum < 100) - return true; - else - return false; + if (layerNum < 100) + return true; + else + return false; } //----------------------------------------------------------------------------- @@ -1615,19 +1478,19 @@ bool PerfectAI::shallRetroAnalysisBeUsed(unsigned int layerNum) //----------------------------------------------------------------------------- unsigned int PerfectAI::getNumberOfKnotsInLayer(unsigned int layerNum) { - // locals - unsigned int numberOfKnots = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; + // locals + unsigned int numberOfKnots = layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1; - // times two since either an own stone must be moved or an opponent stone must be removed - numberOfKnots *= MAX_NUM_STONES_REMOVED_MINUS_1; + // times two since either an own stone must be moved or an opponent stone must be removed + numberOfKnots *= MAX_NUM_STONES_REMOVED_MINUS_1; - // return zero if layer is not reachable - if (((layer[layerNum].numBlackStones < 2 || layer[layerNum].numWhiteStones < 2) && layerNum < 100) // moving phase - || (layer[layerNum].numBlackStones == 2 && layer[layerNum].numWhiteStones == 2 && layerNum < 100) || (layerNum == 100)) - return 0; + // return zero if layer is not reachable + if (((layer[layerNum].numBlackStones < 2 || layer[layerNum].numWhiteStones < 2) && layerNum < 100) // moving phase + || (layer[layerNum].numBlackStones == 2 && layer[layerNum].numWhiteStones == 2 && layerNum < 100) || (layerNum == 100)) + return 0; - // another way - return (unsigned int)numberOfKnots; + // another way + return (unsigned int)numberOfKnots; } //----------------------------------------------------------------------------- @@ -1636,31 +1499,31 @@ unsigned int PerfectAI::getNumberOfKnotsInLayer(unsigned int layerNum) //----------------------------------------------------------------------------- long long PerfectAI::mOverN_Function(unsigned int m, unsigned int n) { - // locals - long long result = 1; - long long fakN = 1; - unsigned int i; + // locals + long long result = 1; + long long fakN = 1; + unsigned int i; - // invalid parameters ? - if (n > m) - return 0; + // invalid parameters ? + if (n > m) + return 0; - // flip, since then the result value won't get so high - if (n > m / 2) - n = m - n; + // flip, since then the result value won't get so high + if (n > m / 2) + n = m - n; - // calc number of possibilities one can put n different stones in m holes - for (i = m - n + 1; i <= m; i++) - result *= i; + // calc number of possibilities one can put n different stones in m holes + for (i = m - n + 1; i <= m; i++) + result *= i; - // calc number of possibilities one can sort n different stones - for (i = 1; i <= n; i++) - fakN *= i; + // calc number of possibilities one can sort n different stones + for (i = 1; i <= n; i++) + fakN *= i; - // divide - result /= fakN; + // divide + result /= fakN; - return result; + return result; } //----------------------------------------------------------------------------- @@ -1669,10 +1532,9 @@ long long PerfectAI::mOverN_Function(unsigned int m, unsigned int n) //----------------------------------------------------------------------------- void PerfectAI::applySymmetrieOperationOnField(unsigned char symmetryOperationNumber, unsigned int *sourceField, unsigned int *destField) { - for (unsigned int i = 0; i < fieldStruct::size; i++) - { - destField[i] = sourceField[symmetryOperationTable[symmetryOperationNumber][i]]; - } + for (unsigned int i = 0; i < fieldStruct::size; i++) { + destField[i] = sourceField[symmetryOperationTable[symmetryOperationNumber][i]]; + } } //----------------------------------------------------------------------------- @@ -1681,11 +1543,11 @@ void PerfectAI::applySymmetrieOperationOnField(unsigned char symmetryOperationNu //----------------------------------------------------------------------------- unsigned int PerfectAI::getLayerNumber(unsigned int threadNo) { - ThreadVars *tv = &threadVars[threadNo]; - unsigned int numBlackStones = tv->field->oppPlayer->numStones; - unsigned int numWhiteStones = tv->field->curPlayer->numStones; - unsigned int phaseIndex = (tv->field->settingPhase == true) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; - return layerIndex[phaseIndex][numWhiteStones][numBlackStones]; + ThreadVars *tv = &threadVars[threadNo]; + unsigned int numBlackStones = tv->field->oppPlayer->numStones; + unsigned int numWhiteStones = tv->field->curPlayer->numStones; + unsigned int phaseIndex = (tv->field->settingPhase == true) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; + return layerIndex[phaseIndex][numWhiteStones][numBlackStones]; } //----------------------------------------------------------------------------- @@ -1694,8 +1556,8 @@ unsigned int PerfectAI::getLayerNumber(unsigned int threadNo) //----------------------------------------------------------------------------- unsigned int PerfectAI::getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber) { - ThreadVars *tv = &threadVars[threadNo]; - return tv->getLayerAndStateNumber(layerNum, stateNumber); + ThreadVars *tv = &threadVars[threadNo]; + return tv->getLayerAndStateNumber(layerNum, stateNumber); } //----------------------------------------------------------------------------- @@ -1704,57 +1566,51 @@ unsigned int PerfectAI::getLayerAndStateNumber(unsigned int threadNo, unsigned i //----------------------------------------------------------------------------- unsigned int PerfectAI::ThreadVars::getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber) { - // locals - unsigned int myField[fieldStruct::size]; - unsigned int symField[fieldStruct::size]; - unsigned int numBlackStones = field->oppPlayer->numStones; - unsigned int numWhiteStones = field->curPlayer->numStones; - unsigned int phaseIndex = (field->settingPhase == true) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; - unsigned int wCD = 0, bCD = 0; - unsigned int stateAB, stateCD; - unsigned int i; + // locals + unsigned int myField[fieldStruct::size]; + unsigned int symField[fieldStruct::size]; + unsigned int numBlackStones = field->oppPlayer->numStones; + unsigned int numWhiteStones = field->curPlayer->numStones; + unsigned int phaseIndex = (field->settingPhase == true) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; + unsigned int wCD = 0, bCD = 0; + unsigned int stateAB, stateCD; + unsigned int i; - // layer number - layerNum = parent->layerIndex[phaseIndex][numWhiteStones][numBlackStones]; + // layer number + layerNum = parent->layerIndex[phaseIndex][numWhiteStones][numBlackStones]; - // make white and black fields - for (i = 0; i < fieldStruct::size; i++) - { - if (field->board[i] == fieldStruct::squareIsFree) - { - myField[i] = FREE_SQUARE; - } - else if (field->board[i] == field->curPlayer->id) - { - myField[i] = WHITE_STONE; - if (fieldPosIsOfGroup[i] == GROUP_C) - wCD++; - if (fieldPosIsOfGroup[i] == GROUP_D) - wCD++; - } - else - { - myField[i] = BLACK_STONE; - if (fieldPosIsOfGroup[i] == GROUP_C) - bCD++; - if (fieldPosIsOfGroup[i] == GROUP_D) - bCD++; - } - } + // make white and black fields + for (i = 0; i < fieldStruct::size; i++) { + if (field->board[i] == fieldStruct::squareIsFree) { + myField[i] = FREE_SQUARE; + } else if (field->board[i] == field->curPlayer->id) { + myField[i] = WHITE_STONE; + if (fieldPosIsOfGroup[i] == GROUP_C) + wCD++; + if (fieldPosIsOfGroup[i] == GROUP_D) + wCD++; + } else { + myField[i] = BLACK_STONE; + if (fieldPosIsOfGroup[i] == GROUP_C) + bCD++; + if (fieldPosIsOfGroup[i] == GROUP_D) + bCD++; + } + } - // calc stateCD - stateCD = myField[squareIndexGroupC[0]] * parent->powerOfThree[15] + myField[squareIndexGroupC[1]] * parent->powerOfThree[14] + myField[squareIndexGroupC[2]] * parent->powerOfThree[13] + myField[squareIndexGroupC[3]] * parent->powerOfThree[12] + myField[squareIndexGroupC[4]] * parent->powerOfThree[11] + myField[squareIndexGroupC[5]] * parent->powerOfThree[10] + myField[squareIndexGroupC[6]] * parent->powerOfThree[9] + myField[squareIndexGroupC[7]] * parent->powerOfThree[8] + myField[squareIndexGroupD[0]] * parent->powerOfThree[7] + myField[squareIndexGroupD[1]] * parent->powerOfThree[6] + myField[squareIndexGroupD[2]] * parent->powerOfThree[5] + myField[squareIndexGroupD[3]] * parent->powerOfThree[4] + myField[squareIndexGroupD[4]] * parent->powerOfThree[3] + myField[squareIndexGroupD[5]] * parent->powerOfThree[2] + myField[squareIndexGroupD[6]] * parent->powerOfThree[1] + myField[squareIndexGroupD[7]] * parent->powerOfThree[0]; + // calc stateCD + stateCD = myField[squareIndexGroupC[0]] * parent->powerOfThree[15] + myField[squareIndexGroupC[1]] * parent->powerOfThree[14] + myField[squareIndexGroupC[2]] * parent->powerOfThree[13] + myField[squareIndexGroupC[3]] * parent->powerOfThree[12] + myField[squareIndexGroupC[4]] * parent->powerOfThree[11] + myField[squareIndexGroupC[5]] * parent->powerOfThree[10] + myField[squareIndexGroupC[6]] * parent->powerOfThree[9] + myField[squareIndexGroupC[7]] * parent->powerOfThree[8] + myField[squareIndexGroupD[0]] * parent->powerOfThree[7] + myField[squareIndexGroupD[1]] * parent->powerOfThree[6] + myField[squareIndexGroupD[2]] * parent->powerOfThree[5] + myField[squareIndexGroupD[3]] * parent->powerOfThree[4] + myField[squareIndexGroupD[4]] * parent->powerOfThree[3] + myField[squareIndexGroupD[5]] * parent->powerOfThree[2] + myField[squareIndexGroupD[6]] * parent->powerOfThree[1] + myField[squareIndexGroupD[7]] * parent->powerOfThree[0]; - // apply symmetry operation on group A&B - parent->applySymmetrieOperationOnField(parent->symmetryOperationCD[stateCD], myField, symField); + // apply symmetry operation on group A&B + parent->applySymmetrieOperationOnField(parent->symmetryOperationCD[stateCD], myField, symField); - // calc stateAB - stateAB = symField[squareIndexGroupA[0]] * parent->powerOfThree[7] + symField[squareIndexGroupA[1]] * parent->powerOfThree[6] + symField[squareIndexGroupA[2]] * parent->powerOfThree[5] + symField[squareIndexGroupA[3]] * parent->powerOfThree[4] + symField[squareIndexGroupB[0]] * parent->powerOfThree[3] + symField[squareIndexGroupB[1]] * parent->powerOfThree[2] + symField[squareIndexGroupB[2]] * parent->powerOfThree[1] + symField[squareIndexGroupB[3]] * parent->powerOfThree[0]; + // calc stateAB + stateAB = symField[squareIndexGroupA[0]] * parent->powerOfThree[7] + symField[squareIndexGroupA[1]] * parent->powerOfThree[6] + symField[squareIndexGroupA[2]] * parent->powerOfThree[5] + symField[squareIndexGroupA[3]] * parent->powerOfThree[4] + symField[squareIndexGroupB[0]] * parent->powerOfThree[3] + symField[squareIndexGroupB[1]] * parent->powerOfThree[2] + symField[squareIndexGroupB[2]] * parent->powerOfThree[1] + symField[squareIndexGroupB[3]] * parent->powerOfThree[0]; - // calc index - stateNumber = parent->layer[layerNum].subLayer[parent->layer[layerNum].subLayerIndexCD[wCD][bCD]].minIndex * MAX_NUM_STONES_REMOVED_MINUS_1 + parent->indexAB[stateAB] * parent->anzahlStellungenCD[wCD][bCD] * MAX_NUM_STONES_REMOVED_MINUS_1 + parent->indexCD[stateCD] * MAX_NUM_STONES_REMOVED_MINUS_1 + field->stoneMustBeRemoved; + // calc index + stateNumber = parent->layer[layerNum].subLayer[parent->layer[layerNum].subLayerIndexCD[wCD][bCD]].minIndex * MAX_NUM_STONES_REMOVED_MINUS_1 + parent->indexAB[stateAB] * parent->anzahlStellungenCD[wCD][bCD] * MAX_NUM_STONES_REMOVED_MINUS_1 + parent->indexCD[stateCD] * MAX_NUM_STONES_REMOVED_MINUS_1 + field->stoneMustBeRemoved; - return parent->symmetryOperationCD[stateCD]; + return parent->symmetryOperationCD[stateCD]; } //----------------------------------------------------------------------------- @@ -1764,181 +1620,167 @@ unsigned int PerfectAI::ThreadVars::getLayerAndStateNumber(unsigned int &layerNu //----------------------------------------------------------------------------- bool PerfectAI::setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber) { - // parameters ok ? - if (getNumberOfLayers() <= layerNum) - return false; - if (getNumberOfKnotsInLayer(layerNum) <= stateNumber) - return false; + // parameters ok ? + if (getNumberOfLayers() <= layerNum) + return false; + if (getNumberOfKnotsInLayer(layerNum) <= stateNumber) + return false; - // locals - ThreadVars *tv = &threadVars[threadNo]; - unsigned int stateNumberWithInSubLayer; - unsigned int stateNumberWithInAB; - unsigned int stateNumberWithInCD; - unsigned int stateAB, stateCD; - unsigned int myField[fieldStruct::size]; - unsigned int symField[fieldStruct::size]; - unsigned int numWhiteStones = layer[layerNum].numWhiteStones; - unsigned int numBlackStones = layer[layerNum].numBlackStones; - unsigned int numberOfMillsCurrentPlayer = 0; - unsigned int numberOfMillsOpponentPlayer = 0; - unsigned int wCD, bCD, wAB, bAB; - unsigned int i; - bool aStoneCanBeRemovedFromCurPlayer; + // locals + ThreadVars *tv = &threadVars[threadNo]; + unsigned int stateNumberWithInSubLayer; + unsigned int stateNumberWithInAB; + unsigned int stateNumberWithInCD; + unsigned int stateAB, stateCD; + unsigned int myField[fieldStruct::size]; + unsigned int symField[fieldStruct::size]; + unsigned int numWhiteStones = layer[layerNum].numWhiteStones; + unsigned int numBlackStones = layer[layerNum].numBlackStones; + unsigned int numberOfMillsCurrentPlayer = 0; + unsigned int numberOfMillsOpponentPlayer = 0; + unsigned int wCD, bCD, wAB, bAB; + unsigned int i; + bool aStoneCanBeRemovedFromCurPlayer; - // get wCD, bCD, wAB, bAB - for (i = 0; i <= layer[layerNum].numSubLayers; i++) - { - if (layer[layerNum].subLayer[i].minIndex <= stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1 && layer[layerNum].subLayer[i].maxIndex >= stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1) - { - wCD = layer[layerNum].subLayer[i].numWhiteStonesGroupCD; - bCD = layer[layerNum].subLayer[i].numBlackStonesGroupCD; - wAB = layer[layerNum].subLayer[i].numWhiteStonesGroupAB; - bAB = layer[layerNum].subLayer[i].numBlackStonesGroupAB; - break; - } - } + // get wCD, bCD, wAB, bAB + for (i = 0; i <= layer[layerNum].numSubLayers; i++) { + if (layer[layerNum].subLayer[i].minIndex <= stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1 && layer[layerNum].subLayer[i].maxIndex >= stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1) { + wCD = layer[layerNum].subLayer[i].numWhiteStonesGroupCD; + bCD = layer[layerNum].subLayer[i].numBlackStonesGroupCD; + wAB = layer[layerNum].subLayer[i].numWhiteStonesGroupAB; + bAB = layer[layerNum].subLayer[i].numBlackStonesGroupAB; + break; + } + } - // reset values - tv->curSearchDepth = 0; - tv->floatValue = 0.0f; - tv->shortValue = SKV_VALUE_GAME_DRAWN; - tv->gameHasFinished = false; + // reset values + tv->curSearchDepth = 0; + tv->floatValue = 0.0f; + tv->shortValue = SKV_VALUE_GAME_DRAWN; + tv->gameHasFinished = false; - tv->field->settingPhase = (layerNum >= NUM_LAYERS / 2) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; - tv->field->stoneMustBeRemoved = stateNumber % MAX_NUM_STONES_REMOVED_MINUS_1; - tv->field->curPlayer->numStones = numWhiteStones; - tv->field->oppPlayer->numStones = numBlackStones; + tv->field->settingPhase = (layerNum >= NUM_LAYERS / 2) ? LAYER_INDEX_SETTING_PHASE : LAYER_INDEX_MOVING_PHASE; + tv->field->stoneMustBeRemoved = stateNumber % MAX_NUM_STONES_REMOVED_MINUS_1; + tv->field->curPlayer->numStones = numWhiteStones; + tv->field->oppPlayer->numStones = numBlackStones; - // reconstruct board->board[] - stateNumberWithInSubLayer = (stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1) - layer[layerNum].subLayer[layer[layerNum].subLayerIndexCD[wCD][bCD]].minIndex; - stateNumberWithInAB = stateNumberWithInSubLayer / anzahlStellungenCD[wCD][bCD]; - stateNumberWithInCD = stateNumberWithInSubLayer % anzahlStellungenCD[wCD][bCD]; + // reconstruct board->board[] + stateNumberWithInSubLayer = (stateNumber / MAX_NUM_STONES_REMOVED_MINUS_1) - layer[layerNum].subLayer[layer[layerNum].subLayerIndexCD[wCD][bCD]].minIndex; + stateNumberWithInAB = stateNumberWithInSubLayer / anzahlStellungenCD[wCD][bCD]; + stateNumberWithInCD = stateNumberWithInSubLayer % anzahlStellungenCD[wCD][bCD]; - // get stateCD - stateCD = originalStateCD[wCD][bCD][stateNumberWithInCD]; - stateAB = originalStateAB[wAB][bAB][stateNumberWithInAB]; + // get stateCD + stateCD = originalStateCD[wCD][bCD][stateNumberWithInCD]; + stateAB = originalStateAB[wAB][bAB][stateNumberWithInAB]; - // set myField from stateCD and stateAB - myField[squareIndexGroupA[0]] = (stateAB / powerOfThree[7]) % 3; - myField[squareIndexGroupA[1]] = (stateAB / powerOfThree[6]) % 3; - myField[squareIndexGroupA[2]] = (stateAB / powerOfThree[5]) % 3; - myField[squareIndexGroupA[3]] = (stateAB / powerOfThree[4]) % 3; - myField[squareIndexGroupB[0]] = (stateAB / powerOfThree[3]) % 3; - myField[squareIndexGroupB[1]] = (stateAB / powerOfThree[2]) % 3; - myField[squareIndexGroupB[2]] = (stateAB / powerOfThree[1]) % 3; - myField[squareIndexGroupB[3]] = (stateAB / powerOfThree[0]) % 3; + // set myField from stateCD and stateAB + myField[squareIndexGroupA[0]] = (stateAB / powerOfThree[7]) % 3; + myField[squareIndexGroupA[1]] = (stateAB / powerOfThree[6]) % 3; + myField[squareIndexGroupA[2]] = (stateAB / powerOfThree[5]) % 3; + myField[squareIndexGroupA[3]] = (stateAB / powerOfThree[4]) % 3; + myField[squareIndexGroupB[0]] = (stateAB / powerOfThree[3]) % 3; + myField[squareIndexGroupB[1]] = (stateAB / powerOfThree[2]) % 3; + myField[squareIndexGroupB[2]] = (stateAB / powerOfThree[1]) % 3; + myField[squareIndexGroupB[3]] = (stateAB / powerOfThree[0]) % 3; - myField[squareIndexGroupC[0]] = (stateCD / powerOfThree[15]) % 3; - myField[squareIndexGroupC[1]] = (stateCD / powerOfThree[14]) % 3; - myField[squareIndexGroupC[2]] = (stateCD / powerOfThree[13]) % 3; - myField[squareIndexGroupC[3]] = (stateCD / powerOfThree[12]) % 3; - myField[squareIndexGroupC[4]] = (stateCD / powerOfThree[11]) % 3; - myField[squareIndexGroupC[5]] = (stateCD / powerOfThree[10]) % 3; - myField[squareIndexGroupC[6]] = (stateCD / powerOfThree[9]) % 3; - myField[squareIndexGroupC[7]] = (stateCD / powerOfThree[8]) % 3; - myField[squareIndexGroupD[0]] = (stateCD / powerOfThree[7]) % 3; - myField[squareIndexGroupD[1]] = (stateCD / powerOfThree[6]) % 3; - myField[squareIndexGroupD[2]] = (stateCD / powerOfThree[5]) % 3; - myField[squareIndexGroupD[3]] = (stateCD / powerOfThree[4]) % 3; - myField[squareIndexGroupD[4]] = (stateCD / powerOfThree[3]) % 3; - myField[squareIndexGroupD[5]] = (stateCD / powerOfThree[2]) % 3; - myField[squareIndexGroupD[6]] = (stateCD / powerOfThree[1]) % 3; - myField[squareIndexGroupD[7]] = (stateCD / powerOfThree[0]) % 3; + myField[squareIndexGroupC[0]] = (stateCD / powerOfThree[15]) % 3; + myField[squareIndexGroupC[1]] = (stateCD / powerOfThree[14]) % 3; + myField[squareIndexGroupC[2]] = (stateCD / powerOfThree[13]) % 3; + myField[squareIndexGroupC[3]] = (stateCD / powerOfThree[12]) % 3; + myField[squareIndexGroupC[4]] = (stateCD / powerOfThree[11]) % 3; + myField[squareIndexGroupC[5]] = (stateCD / powerOfThree[10]) % 3; + myField[squareIndexGroupC[6]] = (stateCD / powerOfThree[9]) % 3; + myField[squareIndexGroupC[7]] = (stateCD / powerOfThree[8]) % 3; + myField[squareIndexGroupD[0]] = (stateCD / powerOfThree[7]) % 3; + myField[squareIndexGroupD[1]] = (stateCD / powerOfThree[6]) % 3; + myField[squareIndexGroupD[2]] = (stateCD / powerOfThree[5]) % 3; + myField[squareIndexGroupD[3]] = (stateCD / powerOfThree[4]) % 3; + myField[squareIndexGroupD[4]] = (stateCD / powerOfThree[3]) % 3; + myField[squareIndexGroupD[5]] = (stateCD / powerOfThree[2]) % 3; + myField[squareIndexGroupD[6]] = (stateCD / powerOfThree[1]) % 3; + myField[squareIndexGroupD[7]] = (stateCD / powerOfThree[0]) % 3; - // apply symmetry operation on group A&B - applySymmetrieOperationOnField(reverseSymOperation[symmetryOperationCD[stateCD]], myField, symField); + // apply symmetry operation on group A&B + applySymmetrieOperationOnField(reverseSymOperation[symmetryOperationCD[stateCD]], myField, symField); - // translate symField[] to board->board[] - for (i = 0; i < fieldStruct::size; i++) - { - if (symField[i] == FREE_SQUARE) - tv->field->board[i] = fieldStruct::squareIsFree; - else if (symField[i] == WHITE_STONE) - tv->field->board[i] = tv->field->curPlayer->id; - else - tv->field->board[i] = tv->field->oppPlayer->id; - } + // translate symField[] to board->board[] + for (i = 0; i < fieldStruct::size; i++) { + if (symField[i] == FREE_SQUARE) + tv->field->board[i] = fieldStruct::squareIsFree; + else if (symField[i] == WHITE_STONE) + tv->field->board[i] = tv->field->curPlayer->id; + else + tv->field->board[i] = tv->field->oppPlayer->id; + } - // calc possible moves - tv->calcPossibleMoves(tv->field->curPlayer); - tv->calcPossibleMoves(tv->field->oppPlayer); + // calc possible moves + tv->calcPossibleMoves(tv->field->curPlayer); + tv->calcPossibleMoves(tv->field->oppPlayer); - // zero - for (i = 0; i < fieldStruct::size; i++) - { - tv->field->stonePartOfMill[i] = 0; - } + // zero + for (i = 0; i < fieldStruct::size; i++) { + tv->field->stonePartOfMill[i] = 0; + } - // go in every direction - for (i = 0; i < fieldStruct::size; i++) - { - tv->setWarningAndMill(i, tv->field->neighbour[i][0][0], tv->field->neighbour[i][0][1]); - tv->setWarningAndMill(i, tv->field->neighbour[i][1][0], tv->field->neighbour[i][1][1]); - } + // go in every direction + for (i = 0; i < fieldStruct::size; i++) { + tv->setWarningAndMill(i, tv->field->neighbour[i][0][0], tv->field->neighbour[i][0][1]); + tv->setWarningAndMill(i, tv->field->neighbour[i][1][0], tv->field->neighbour[i][1][1]); + } - // since every mill was detected 3 times - for (i = 0; i < fieldStruct::size; i++) - tv->field->stonePartOfMill[i] /= 3; + // since every mill was detected 3 times + for (i = 0; i < fieldStruct::size; i++) + tv->field->stonePartOfMill[i] /= 3; - // count completed mills - for (i = 0; i < fieldStruct::size; i++) - { - if (tv->field->board[i] == tv->field->curPlayer->id) - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; - else - numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; - } + // count completed mills + for (i = 0; i < fieldStruct::size; i++) { + if (tv->field->board[i] == tv->field->curPlayer->id) + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; + else + numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; + } - numberOfMillsCurrentPlayer /= 3; - numberOfMillsOpponentPlayer /= 3; + numberOfMillsCurrentPlayer /= 3; + numberOfMillsOpponentPlayer /= 3; - // stonesSet & numStonesMissing - if (tv->field->settingPhase) - { - // BUG: ... This calculation is not correct! It is possible that some mills did not cause a stone removal. - tv->field->curPlayer->numStonesMissing = numberOfMillsOpponentPlayer; - tv->field->oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - tv->field->stoneMustBeRemoved; - tv->field->stonesSet = tv->field->curPlayer->numStones + tv->field->oppPlayer->numStones + tv->field->curPlayer->numStonesMissing + tv->field->oppPlayer->numStonesMissing; - } - else - { - tv->field->stonesSet = 18; - tv->field->curPlayer->numStonesMissing = 9 - tv->field->curPlayer->numStones; - tv->field->oppPlayer->numStonesMissing = 9 - tv->field->oppPlayer->numStones; - } + // stonesSet & numStonesMissing + if (tv->field->settingPhase) { + // BUG: ... This calculation is not correct! It is possible that some mills did not cause a stone removal. + tv->field->curPlayer->numStonesMissing = numberOfMillsOpponentPlayer; + tv->field->oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - tv->field->stoneMustBeRemoved; + tv->field->stonesSet = tv->field->curPlayer->numStones + tv->field->oppPlayer->numStones + tv->field->curPlayer->numStonesMissing + tv->field->oppPlayer->numStonesMissing; + } else { + tv->field->stonesSet = 18; + tv->field->curPlayer->numStonesMissing = 9 - tv->field->curPlayer->numStones; + tv->field->oppPlayer->numStonesMissing = 9 - tv->field->oppPlayer->numStones; + } - // when opponent is unable to move than current player has won - if ((!tv->field->curPlayer->numPossibleMoves) && (!tv->field->settingPhase) && (!tv->field->stoneMustBeRemoved) && (tv->field->curPlayer->numStones > 3)) - { - tv->gameHasFinished = true; - tv->shortValue = SKV_VALUE_GAME_LOST; - } - if ((tv->field->curPlayer->numStones < 3) && (!tv->field->settingPhase)) - { - tv->gameHasFinished = true; - tv->shortValue = SKV_VALUE_GAME_LOST; - } - if ((tv->field->oppPlayer->numStones < 3) && (!tv->field->settingPhase)) - { - tv->gameHasFinished = true; - tv->shortValue = SKV_VALUE_GAME_WON; - } + // when opponent is unable to move than current player has won + if ((!tv->field->curPlayer->numPossibleMoves) && (!tv->field->settingPhase) && (!tv->field->stoneMustBeRemoved) && (tv->field->curPlayer->numStones > 3)) { + tv->gameHasFinished = true; + tv->shortValue = SKV_VALUE_GAME_LOST; + } + if ((tv->field->curPlayer->numStones < 3) && (!tv->field->settingPhase)) { + tv->gameHasFinished = true; + tv->shortValue = SKV_VALUE_GAME_LOST; + } + if ((tv->field->oppPlayer->numStones < 3) && (!tv->field->settingPhase)) { + tv->gameHasFinished = true; + tv->shortValue = SKV_VALUE_GAME_WON; + } - tv->floatValue = tv->shortValue; + tv->floatValue = tv->shortValue; - // precalc aStoneCanBeRemovedFromCurPlayer - for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) - { - if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) - { - aStoneCanBeRemovedFromCurPlayer = true; - break; - } - } + // precalc aStoneCanBeRemovedFromCurPlayer + for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) { + if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) { + aStoneCanBeRemovedFromCurPlayer = true; + break; + } + } - // test if board is ok - return tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer); + // test if board is ok + return tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer); } //----------------------------------------------------------------------------- @@ -1947,40 +1789,37 @@ bool PerfectAI::setSituation(unsigned int threadNo, unsigned int layerNum, unsig //----------------------------------------------------------------------------- void PerfectAI::ThreadVars::calcPossibleMoves(Player *player) { - // locals - unsigned int i, j, k, movingDirection; + // locals + unsigned int i, j, k, movingDirection; - for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { + for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { - // is stone from player ? - if (field->board[i] != player->id) - continue; + // is stone from player ? + if (field->board[i] != player->id) + continue; - // is destination free ? - if (field->board[j] != field->squareIsFree) - continue; + // is destination free ? + if (field->board[j] != field->squareIsFree) + continue; - // when current player has only 3 stones he is allowed to spring his stone - if (player->numStones > 3 || field->settingPhase) - { + // when current player has only 3 stones he is allowed to spring his stone + if (player->numStones > 3 || field->settingPhase) { - // determine moving direction - for (k = 0, movingDirection = 4; k < 4; k++) - if (field->connectedSquare[i][k] == j) - movingDirection = k; + // determine moving direction + for (k = 0, movingDirection = 4; k < 4; k++) + if (field->connectedSquare[i][k] == j) + movingDirection = k; - // are both squares connected ? - if (movingDirection == 4) - continue; - } + // are both squares connected ? + if (movingDirection == 4) + continue; + } - // everything is ok - player->numPossibleMoves++; - } - } + // everything is ok + player->numPossibleMoves++; + } + } } //----------------------------------------------------------------------------- @@ -1989,17 +1828,16 @@ void PerfectAI::ThreadVars::calcPossibleMoves(Player *player) //----------------------------------------------------------------------------- void PerfectAI::ThreadVars::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour) { - // locals - int rowOwner = field->board[stone]; + // locals + int rowOwner = field->board[stone]; - // mill closed ? - if (rowOwner != field->squareIsFree && field->board[firstNeighbour] == rowOwner && field->board[secondNeighbour] == rowOwner) - { + // mill closed ? + if (rowOwner != field->squareIsFree && field->board[firstNeighbour] == rowOwner && field->board[secondNeighbour] == rowOwner) { - field->stonePartOfMill[stone]++; - field->stonePartOfMill[firstNeighbour]++; - field->stonePartOfMill[secondNeighbour]++; - } + field->stonePartOfMill[stone]++; + field->stonePartOfMill[firstNeighbour]++; + field->stonePartOfMill[secondNeighbour]++; + } } //----------------------------------------------------------------------------- @@ -2008,9 +1846,9 @@ void PerfectAI::ThreadVars::setWarningAndMill(unsigned int stone, unsigned int f //----------------------------------------------------------------------------- string PerfectAI::getOutputInformation(unsigned int layerNum) { - stringstream ss; - ss << " white stones : " << layer[layerNum].numWhiteStones << " \tblack stones : " << layer[layerNum].numBlackStones; - return ss.str(); + stringstream ss; + ss << " white stones : " << layer[layerNum].numWhiteStones << " \tblack stones : " << layer[layerNum].numBlackStones; + return ss.str(); } //----------------------------------------------------------------------------- @@ -2019,16 +1857,16 @@ string PerfectAI::getOutputInformation(unsigned int layerNum) //----------------------------------------------------------------------------- void PerfectAI::printBoard(unsigned int threadNo, unsigned char value) { - ThreadVars *tv = &threadVars[threadNo]; - char wonStr[] = "WON"; - char lostStr[] = "LOST"; - char drawStr[] = "DRAW"; - char invStr[] = "INVALID"; - char *table[4] = {invStr, lostStr, drawStr, wonStr}; + ThreadVars *tv = &threadVars[threadNo]; + char wonStr[] = "WON"; + char lostStr[] = "LOST"; + char drawStr[] = "DRAW"; + char invStr[] = "INVALID"; + char *table[4] = { invStr, lostStr, drawStr, wonStr }; - cout << "\nstate value : " << table[value]; - cout << "\nstones set : " << tv->field->stonesSet << "\n"; - tv->field->printBoard(); + cout << "\nstate value : " << table[value]; + cout << "\nstones set : " << tv->field->stonesSet << "\n"; + tv->field->printBoard(); } //----------------------------------------------------------------------------- @@ -2037,13 +1875,13 @@ void PerfectAI::printBoard(unsigned int threadNo, unsigned char value) //----------------------------------------------------------------------------- void PerfectAI::getField(unsigned int layerNum, unsigned int stateNumber, fieldStruct *field, bool *gameHasFinished) { - // set current desired state on thread zero - setSituation(0, layerNum, stateNumber); + // set current desired state on thread zero + setSituation(0, layerNum, stateNumber); - // copy content of fieldStruct - threadVars[0].field->copyBoard(field); - if (gameHasFinished != nullptr) - *gameHasFinished = threadVars[0].gameHasFinished; + // copy content of fieldStruct + threadVars[0].field->copyBoard(field); + if (gameHasFinished != nullptr) + *gameHasFinished = threadVars[0].gameHasFinished; } //----------------------------------------------------------------------------- @@ -2052,7 +1890,7 @@ void PerfectAI::getField(unsigned int layerNum, unsigned int stateNumber, fieldS //----------------------------------------------------------------------------- void PerfectAI::getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber /*, unsigned int& symmetryOperation*/) { - /*symmetryOperation = */ threadVars[0].getLayerAndStateNumber(layerNum, stateNumber); + /*symmetryOperation = */ threadVars[0].getLayerAndStateNumber(layerNum, stateNumber); } //----------------------------------------------------------------------------- @@ -2061,8 +1899,8 @@ void PerfectAI::getLayerAndStateNumber(unsigned int &layerNum, unsigned int &sta //----------------------------------------------------------------------------- void PerfectAI::setOpponentLevel(unsigned int threadNo, bool isOpponentLevel) { - ThreadVars *tv = &threadVars[threadNo]; - tv->ownId = isOpponentLevel ? tv->field->oppPlayer->id : tv->field->curPlayer->id; + ThreadVars *tv = &threadVars[threadNo]; + tv->ownId = isOpponentLevel ? tv->field->oppPlayer->id : tv->field->curPlayer->id; } //----------------------------------------------------------------------------- @@ -2071,8 +1909,8 @@ void PerfectAI::setOpponentLevel(unsigned int threadNo, bool isOpponentLevel) //----------------------------------------------------------------------------- bool PerfectAI::getOpponentLevel(unsigned int threadNo) { - ThreadVars *tv = &threadVars[threadNo]; - return (tv->ownId == tv->field->oppPlayer->id); + ThreadVars *tv = &threadVars[threadNo]; + return (tv->ownId == tv->field->oppPlayer->id); } //----------------------------------------------------------------------------- @@ -2081,15 +1919,13 @@ bool PerfectAI::getOpponentLevel(unsigned int threadNo) //----------------------------------------------------------------------------- unsigned int PerfectAI::getPartnerLayer(unsigned int layerNum) { - if (layerNum < 100) - for (int i = 0; i < 100; i++) - { - if (layer[layerNum].numBlackStones == layer[i].numWhiteStones && layer[layerNum].numWhiteStones == layer[i].numBlackStones) - { - return i; - } - } - return layerNum; + if (layerNum < 100) + for (int i = 0; i < 100; i++) { + if (layer[layerNum].numBlackStones == layer[i].numWhiteStones && layer[layerNum].numWhiteStones == layer[i].numBlackStones) { + return i; + } + } + return layerNum; } //----------------------------------------------------------------------------- @@ -2098,32 +1934,28 @@ unsigned int PerfectAI::getPartnerLayer(unsigned int layerNum) //----------------------------------------------------------------------------- void PerfectAI::getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers) { - // locals - unsigned int i; - unsigned int shift = (layerNum >= 100) ? 100 : 0; - int diff = (layerNum >= 100) ? 1 : -1; + // locals + unsigned int i; + unsigned int shift = (layerNum >= 100) ? 100 : 0; + int diff = (layerNum >= 100) ? 1 : -1; - // search layer with one white stone less - for (*amountOfSuccLayers = 0, i = 0 + shift; i < 100 + shift; i++) - { - if (layer[i].numWhiteStones == layer[layerNum].numBlackStones + diff && layer[i].numBlackStones == layer[layerNum].numWhiteStones) - { - succLayers[*amountOfSuccLayers] = i; - *amountOfSuccLayers = *amountOfSuccLayers + 1; - break; - } - } + // search layer with one white stone less + for (*amountOfSuccLayers = 0, i = 0 + shift; i < 100 + shift; i++) { + if (layer[i].numWhiteStones == layer[layerNum].numBlackStones + diff && layer[i].numBlackStones == layer[layerNum].numWhiteStones) { + succLayers[*amountOfSuccLayers] = i; + *amountOfSuccLayers = *amountOfSuccLayers + 1; + break; + } + } - // search layer with one black stone less - for (i = 0 + shift; i < 100 + shift; i++) - { - if (layer[i].numWhiteStones == layer[layerNum].numBlackStones && layer[i].numBlackStones == layer[layerNum].numWhiteStones + diff) - { - succLayers[*amountOfSuccLayers] = i; - *amountOfSuccLayers = *amountOfSuccLayers + 1; - break; - } - } + // search layer with one black stone less + for (i = 0 + shift; i < 100 + shift; i++) { + if (layer[i].numWhiteStones == layer[layerNum].numBlackStones && layer[i].numBlackStones == layer[layerNum].numWhiteStones + diff) { + succLayers[*amountOfSuccLayers] = i; + *amountOfSuccLayers = *amountOfSuccLayers + 1; + break; + } + } } //----------------------------------------------------------------------------- @@ -2132,42 +1964,39 @@ void PerfectAI::getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccL //----------------------------------------------------------------------------- void PerfectAI::getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers) { - // locals - ThreadVars *tv = &threadVars[threadNo]; - int originalField[fieldStruct::size]; - unsigned int originalPartOfMill[fieldStruct::size]; - unsigned int i, symmetryOperation; - unsigned int layerNum, stateNum; + // locals + ThreadVars *tv = &threadVars[threadNo]; + int originalField[fieldStruct::size]; + unsigned int originalPartOfMill[fieldStruct::size]; + unsigned int i, symmetryOperation; + unsigned int layerNum, stateNum; - *numSymmetricStates = 0; - *symStateNumbers = symmetricStateNumberArray; + *numSymmetricStates = 0; + *symStateNumbers = symmetricStateNumberArray; - // save current board - for (i = 0; i < fieldStruct::size; i++) - { - originalField[i] = tv->field->board[i]; - originalPartOfMill[i] = tv->field->stonePartOfMill[i]; - } + // save current board + for (i = 0; i < fieldStruct::size; i++) { + originalField[i] = tv->field->board[i]; + originalPartOfMill[i] = tv->field->stonePartOfMill[i]; + } - // add all symmetric states - for (symmetryOperation = 0; symmetryOperation < NUM_SYM_OPERATIONS; symmetryOperation++) - { + // add all symmetric states + for (symmetryOperation = 0; symmetryOperation < NUM_SYM_OPERATIONS; symmetryOperation++) { - // appy symmetry operation - applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalField, (unsigned int *)tv->field->board); - applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalPartOfMill, (unsigned int *)tv->field->stonePartOfMill); + // appy symmetry operation + applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalField, (unsigned int *)tv->field->board); + applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalPartOfMill, (unsigned int *)tv->field->stonePartOfMill); - getLayerAndStateNumber(threadNo, layerNum, stateNum); - symmetricStateNumberArray[*numSymmetricStates] = stateNum; - (*numSymmetricStates)++; - } + getLayerAndStateNumber(threadNo, layerNum, stateNum); + symmetricStateNumberArray[*numSymmetricStates] = stateNum; + (*numSymmetricStates)++; + } - // restore original board - for (i = 0; i < fieldStruct::size; i++) - { - tv->field->board[i] = originalField[i]; - tv->field->stonePartOfMill[i] = originalPartOfMill[i]; - } + // restore original board + for (i = 0; i < fieldStruct::size; i++) { + tv->field->board[i] = originalField[i]; + tv->field->stonePartOfMill[i] = originalPartOfMill[i]; + } } //----------------------------------------------------------------------------- @@ -2176,57 +2005,48 @@ void PerfectAI::getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *n //----------------------------------------------------------------------------- bool PerfectAI::ThreadVars::fieldIntegrityOK(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, bool aStoneCanBeRemovedFromCurPlayer) { - // locals - int i, j; - bool noneFullFilled; + // locals + int i, j; + bool noneFullFilled; - // when stone is going to be removed than at least one opponent stone mustn't be part of a mill - if (numberOfMillsOpponentPlayer > 0 && field->stoneMustBeRemoved) - { - for (i = 0; i < field->size; i++) - if (field->stonePartOfMill[i] == 0 && field->oppPlayer->id == field->board[i]) - break; - if (i == field->size) - return false; - } + // when stone is going to be removed than at least one opponent stone mustn't be part of a mill + if (numberOfMillsOpponentPlayer > 0 && field->stoneMustBeRemoved) { + for (i = 0; i < field->size; i++) + if (field->stonePartOfMill[i] == 0 && field->oppPlayer->id == field->board[i]) + break; + if (i == field->size) + return false; + } - // when no mill is closed than no stone can be removed - if (field->stoneMustBeRemoved && numberOfMillsCurrentPlayer == 0) - { - return false; + // when no mill is closed than no stone can be removed + if (field->stoneMustBeRemoved && numberOfMillsCurrentPlayer == 0) { + return false; - // when in setting phase and difference in number of stones between the two players is not - } - else if (field->settingPhase) - { + // when in setting phase and difference in number of stones between the two players is not + } else if (field->settingPhase) { - // Version 8: added for-loop - noneFullFilled = true; + // Version 8: added for-loop + noneFullFilled = true; - for (i = 0; noneFullFilled && i <= (int)numberOfMillsOpponentPlayer && i <= (int)numberOfMillsCurrentPlayer; i++) - { - for (j = 0; noneFullFilled && j <= (int)numberOfMillsOpponentPlayer && j <= (int)numberOfMillsCurrentPlayer - (int)field->stoneMustBeRemoved; j++) - { - if (field->curPlayer->numStones + numberOfMillsOpponentPlayer + 0 - field->stoneMustBeRemoved - j == field->oppPlayer->numStones + numberOfMillsCurrentPlayer - field->stoneMustBeRemoved - i) - noneFullFilled = false; - if (field->curPlayer->numStones + numberOfMillsOpponentPlayer + 1 - field->stoneMustBeRemoved - j == field->oppPlayer->numStones + numberOfMillsCurrentPlayer - field->stoneMustBeRemoved - i) - noneFullFilled = false; - } - } + for (i = 0; noneFullFilled && i <= (int)numberOfMillsOpponentPlayer && i <= (int)numberOfMillsCurrentPlayer; i++) { + for (j = 0; noneFullFilled && j <= (int)numberOfMillsOpponentPlayer && j <= (int)numberOfMillsCurrentPlayer - (int)field->stoneMustBeRemoved; j++) { + if (field->curPlayer->numStones + numberOfMillsOpponentPlayer + 0 - field->stoneMustBeRemoved - j == field->oppPlayer->numStones + numberOfMillsCurrentPlayer - field->stoneMustBeRemoved - i) + noneFullFilled = false; + if (field->curPlayer->numStones + numberOfMillsOpponentPlayer + 1 - field->stoneMustBeRemoved - j == field->oppPlayer->numStones + numberOfMillsCurrentPlayer - field->stoneMustBeRemoved - i) + noneFullFilled = false; + } + } - if (noneFullFilled || field->stonesSet >= 18) - { - return false; - } + if (noneFullFilled || field->stonesSet >= 18) { + return false; + } - // moving phase - } - else if (!field->settingPhase && (field->curPlayer->numStones < 2 || field->oppPlayer->numStones < 2)) - { - return false; - } + // moving phase + } else if (!field->settingPhase && (field->curPlayer->numStones < 2 || field->oppPlayer->numStones < 2)) { + return false; + } - return true; + return true; } //----------------------------------------------------------------------------- @@ -2235,59 +2055,59 @@ bool PerfectAI::ThreadVars::fieldIntegrityOK(unsigned int numberOfMillsCurrentPl //----------------------------------------------------------------------------- bool PerfectAI::isSymOperationInvariantOnGroupCD(unsigned int symmetryOperation, int *theField) { - // locals - unsigned int i; + // locals + unsigned int i; - i = squareIndexGroupC[0]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[1]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[2]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[3]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[4]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[5]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[6]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupC[7]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[0]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[1]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[2]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[3]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[4]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[5]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[6]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; - i = squareIndexGroupD[7]; - if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) - return false; + i = squareIndexGroupC[0]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[1]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[2]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[3]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[4]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[5]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[6]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupC[7]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[0]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[1]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[2]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[3]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[4]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[5]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[6]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; + i = squareIndexGroupD[7]; + if (theField[i] != theField[symmetryOperationTable[symmetryOperation][i]]) + return false; - return true; + return true; } //----------------------------------------------------------------------------- @@ -2296,50 +2116,47 @@ bool PerfectAI::isSymOperationInvariantOnGroupCD(unsigned int symmetryOperation, //----------------------------------------------------------------------------- void PerfectAI::ThreadVars::storePredecessor(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars) { - // locals - int originalField[fieldStruct::size]; - unsigned int i, symmetryOperation, symOpApplied; - unsigned int predLayerNum, predStateNum; - unsigned int originalAmountOfPred = *amountOfPred; + // locals + int originalField[fieldStruct::size]; + unsigned int i, symmetryOperation, symOpApplied; + unsigned int predLayerNum, predStateNum; + unsigned int originalAmountOfPred = *amountOfPred; - // store only if state is valid - if (fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, false)) - { + // store only if state is valid + if (fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, false)) { - // save current board - for (i = 0; i < fieldStruct::size; i++) - originalField[i] = field->board[i]; + // save current board + for (i = 0; i < fieldStruct::size; i++) + originalField[i] = field->board[i]; - // add all symmetric states - for (symmetryOperation = 0; symmetryOperation < NUM_SYM_OPERATIONS; symmetryOperation++) - { + // add all symmetric states + for (symmetryOperation = 0; symmetryOperation < NUM_SYM_OPERATIONS; symmetryOperation++) { - // ... - if (symmetryOperation == SO_DO_NOTHING || parent->isSymOperationInvariantOnGroupCD(symmetryOperation, originalField)) - { + // ... + if (symmetryOperation == SO_DO_NOTHING || parent->isSymOperationInvariantOnGroupCD(symmetryOperation, originalField)) { - // appy symmetry operation - parent->applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalField, (unsigned int *)field->board); + // appy symmetry operation + parent->applySymmetrieOperationOnField(symmetryOperation, (unsigned int *)originalField, (unsigned int *)field->board); - symOpApplied = getLayerAndStateNumber(predLayerNum, predStateNum); - predVars[*amountOfPred].predSymOperation = parent->concSymOperation[symmetryOperation][symOpApplied]; - predVars[*amountOfPred].predLayerNumbers = predLayerNum; - predVars[*amountOfPred].predStateNumbers = predStateNum; - predVars[*amountOfPred].playerToMoveChanged = predVars[originalAmountOfPred].playerToMoveChanged; + symOpApplied = getLayerAndStateNumber(predLayerNum, predStateNum); + predVars[*amountOfPred].predSymOperation = parent->concSymOperation[symmetryOperation][symOpApplied]; + predVars[*amountOfPred].predLayerNumbers = predLayerNum; + predVars[*amountOfPred].predStateNumbers = predStateNum; + predVars[*amountOfPred].playerToMoveChanged = predVars[originalAmountOfPred].playerToMoveChanged; - // add only if not already in list - for (i = 0; i < (*amountOfPred); i++) - if (predVars[i].predLayerNumbers == predLayerNum && predVars[i].predStateNumbers == predStateNum) - break; - if (i == *amountOfPred) - (*amountOfPred)++; - } - } + // add only if not already in list + for (i = 0; i < (*amountOfPred); i++) + if (predVars[i].predLayerNumbers == predLayerNum && predVars[i].predStateNumbers == predStateNum) + break; + if (i == *amountOfPred) + (*amountOfPred)++; + } + } - // restore original board - for (i = 0; i < fieldStruct::size; i++) - field->board[i] = originalField[i]; - } + // restore original board + for (i = 0; i < fieldStruct::size; i++) + field->board[i] = originalField[i]; + } } //----------------------------------------------------------------------------- @@ -2348,273 +2165,242 @@ void PerfectAI::ThreadVars::storePredecessor(unsigned int numberOfMillsCurrentPl //----------------------------------------------------------------------------- void PerfectAI::getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars) { - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // the important variables, which much be updated for the getLayerAndStateNumber function are the following ones: - // - board->curPlayer->numStones - // - board->oppPlayer->numStones - // - board->curPlayer->id - // - board->board - // - board->stoneMustBeRemoved - // - board->settingPhase - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // the important variables, which much be updated for the getLayerAndStateNumber function are the following ones: + // - board->curPlayer->numStones + // - board->oppPlayer->numStones + // - board->curPlayer->id + // - board->board + // - board->stoneMustBeRemoved + // - board->settingPhase + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // locals - ThreadVars *tv = &threadVars[threadNo]; - bool aStoneCanBeRemovedFromCurPlayer; - bool millWasClosed; - unsigned int from, to, dir, i; - Player *tmpPlayer; - unsigned int numberOfMillsCurrentPlayer = 0; - unsigned int numberOfMillsOpponentPlayer = 0; + // locals + ThreadVars *tv = &threadVars[threadNo]; + bool aStoneCanBeRemovedFromCurPlayer; + bool millWasClosed; + unsigned int from, to, dir, i; + Player *tmpPlayer; + unsigned int numberOfMillsCurrentPlayer = 0; + unsigned int numberOfMillsOpponentPlayer = 0; - // zero - *amountOfPred = 0; + // zero + *amountOfPred = 0; - // count completed mills - for (i = 0; i < fieldStruct::size; i++) - { - if (tv->field->board[i] == tv->field->curPlayer->id) - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; - else - numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; - } + // count completed mills + for (i = 0; i < fieldStruct::size; i++) { + if (tv->field->board[i] == tv->field->curPlayer->id) + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; + else + numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; + } - numberOfMillsCurrentPlayer /= 3; - numberOfMillsOpponentPlayer /= 3; + numberOfMillsCurrentPlayer /= 3; + numberOfMillsOpponentPlayer /= 3; - // precalc aStoneCanBeRemovedFromCurPlayer - for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) - { - if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) - { - aStoneCanBeRemovedFromCurPlayer = true; - break; - } - } + // precalc aStoneCanBeRemovedFromCurPlayer + for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) { + if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) { + aStoneCanBeRemovedFromCurPlayer = true; + break; + } + } - // was a mill closed? - if (tv->field->stoneMustBeRemoved) - millWasClosed = true; - else - millWasClosed = false; + // was a mill closed? + if (tv->field->stoneMustBeRemoved) + millWasClosed = true; + else + millWasClosed = false; - // in moving phase - if (!tv->field->settingPhase && tv->field->curPlayer->numStones >= 3 && tv->field->oppPlayer->numStones >= 3) - { + // in moving phase + if (!tv->field->settingPhase && tv->field->curPlayer->numStones >= 3 && tv->field->oppPlayer->numStones >= 3) { - // normal move - if ((tv->field->stoneMustBeRemoved && tv->field->curPlayer->numStones > 3) || (!tv->field->stoneMustBeRemoved && tv->field->oppPlayer->numStones > 3)) - { + // normal move + if ((tv->field->stoneMustBeRemoved && tv->field->curPlayer->numStones > 3) || (!tv->field->stoneMustBeRemoved && tv->field->oppPlayer->numStones > 3)) { - // when game has finished then because current player can't move anymore or has less then 3 stones - if (!tv->gameHasFinished || (tv->gameHasFinished && tv->field->curPlayer->numPossibleMoves == 0)) - { + // when game has finished then because current player can't move anymore or has less then 3 stones + if (!tv->gameHasFinished || (tv->gameHasFinished && tv->field->curPlayer->numPossibleMoves == 0)) { - // test each destination - for (to = 0; to < tv->field->size; to++) - { + // test each destination + for (to = 0; to < tv->field->size; to++) { - // was opponent player stone owner? - if (tv->field->board[to] != (tv->field->stoneMustBeRemoved ? tv->field->curPlayer->id : tv->field->oppPlayer->id)) - continue; + // was opponent player stone owner? + if (tv->field->board[to] != (tv->field->stoneMustBeRemoved ? tv->field->curPlayer->id : tv->field->oppPlayer->id)) + continue; - // when stone is going to be removed than a mill must be closed - if (tv->field->stoneMustBeRemoved && tv->field->stonePartOfMill[to] == 0) - continue; + // when stone is going to be removed than a mill must be closed + if (tv->field->stoneMustBeRemoved && tv->field->stonePartOfMill[to] == 0) + continue; - // when stone is part of a mill then a stone must be removed - if (aStoneCanBeRemovedFromCurPlayer && tv->field->stoneMustBeRemoved == 0 && tv->field->stonePartOfMill[to]) - continue; + // when stone is part of a mill then a stone must be removed + if (aStoneCanBeRemovedFromCurPlayer && tv->field->stoneMustBeRemoved == 0 && tv->field->stonePartOfMill[to]) + continue; - // test each direction - for (dir = 0; dir < 4; dir++) - { + // test each direction + for (dir = 0; dir < 4; dir++) { - // origin - from = tv->field->connectedSquare[to][dir]; + // origin + from = tv->field->connectedSquare[to][dir]; - // move possible ? - if (from < tv->field->size && tv->field->board[from] == tv->field->squareIsFree) - { + // move possible ? + if (from < tv->field->size && tv->field->board[from] == tv->field->squareIsFree) { - if (millWasClosed) - { - numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; - tv->field->stoneMustBeRemoved = 0; - predVars[*amountOfPred].playerToMoveChanged = false; - } - else - { - predVars[*amountOfPred].playerToMoveChanged = true; - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; - i = numberOfMillsCurrentPlayer; - numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; - numberOfMillsOpponentPlayer = i; - numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; - } + if (millWasClosed) { + numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; + tv->field->stoneMustBeRemoved = 0; + predVars[*amountOfPred].playerToMoveChanged = false; + } else { + predVars[*amountOfPred].playerToMoveChanged = true; + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; + i = numberOfMillsCurrentPlayer; + numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; + numberOfMillsOpponentPlayer = i; + numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; + } - // make move - tv->field->board[from] = tv->field->board[to]; - tv->field->board[to] = tv->field->squareIsFree; + // make move + tv->field->board[from] = tv->field->board[to]; + tv->field->board[to] = tv->field->squareIsFree; - // store predecessor - tv->storePredecessor(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, amountOfPred, predVars); + // store predecessor + tv->storePredecessor(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, amountOfPred, predVars); - // undo move - tv->field->board[to] = tv->field->board[from]; - tv->field->board[from] = tv->field->squareIsFree; + // undo move + tv->field->board[to] = tv->field->board[from]; + tv->field->board[from] = tv->field->squareIsFree; - if (millWasClosed) - { - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; - tv->field->stoneMustBeRemoved = 1; - } - else - { - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; - i = numberOfMillsCurrentPlayer; - numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; - numberOfMillsOpponentPlayer = i; - } + if (millWasClosed) { + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; + tv->field->stoneMustBeRemoved = 1; + } else { + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; + i = numberOfMillsCurrentPlayer; + numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; + numberOfMillsOpponentPlayer = i; + } - // current or opponent player were allowed to spring - } - } - } - } - } - else if (!tv->gameHasFinished) - { + // current or opponent player were allowed to spring + } + } + } + } + } else if (!tv->gameHasFinished) { - // test each destination - for (to = 0; to < tv->field->size; to++) - { + // test each destination + for (to = 0; to < tv->field->size; to++) { - // when stone must be removed than current player closed a mill, otherwise the opponent did a common spring move - if (tv->field->board[to] != (tv->field->stoneMustBeRemoved ? tv->field->curPlayer->id : tv->field->oppPlayer->id)) - continue; + // when stone must be removed than current player closed a mill, otherwise the opponent did a common spring move + if (tv->field->board[to] != (tv->field->stoneMustBeRemoved ? tv->field->curPlayer->id : tv->field->oppPlayer->id)) + continue; - // when stone is going to be removed than a mill must be closed - if (tv->field->stoneMustBeRemoved && tv->field->stonePartOfMill[to] == 0) - continue; + // when stone is going to be removed than a mill must be closed + if (tv->field->stoneMustBeRemoved && tv->field->stonePartOfMill[to] == 0) + continue; - // when stone is part of a mill then a stone must be removed - if (aStoneCanBeRemovedFromCurPlayer && tv->field->stoneMustBeRemoved == 0 && tv->field->stonePartOfMill[to]) - continue; + // when stone is part of a mill then a stone must be removed + if (aStoneCanBeRemovedFromCurPlayer && tv->field->stoneMustBeRemoved == 0 && tv->field->stonePartOfMill[to]) + continue; - // test each direction - for (from = 0; from < tv->field->size; from++) - { + // test each direction + for (from = 0; from < tv->field->size; from++) { - // move possible ? - if (tv->field->board[from] == tv->field->squareIsFree) - { + // move possible ? + if (tv->field->board[from] == tv->field->squareIsFree) { - // was a mill closed? - if (millWasClosed) - { - numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; - tv->field->stoneMustBeRemoved = 0; - predVars[*amountOfPred].playerToMoveChanged = false; - } - else - { - predVars[*amountOfPred].playerToMoveChanged = true; - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; - i = numberOfMillsCurrentPlayer; - numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; - numberOfMillsOpponentPlayer = i; - numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; - } + // was a mill closed? + if (millWasClosed) { + numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; + tv->field->stoneMustBeRemoved = 0; + predVars[*amountOfPred].playerToMoveChanged = false; + } else { + predVars[*amountOfPred].playerToMoveChanged = true; + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; + i = numberOfMillsCurrentPlayer; + numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; + numberOfMillsOpponentPlayer = i; + numberOfMillsCurrentPlayer -= tv->field->stonePartOfMill[to]; + } - // make move - tv->field->board[from] = tv->field->board[to]; - tv->field->board[to] = tv->field->squareIsFree; + // make move + tv->field->board[from] = tv->field->board[to]; + tv->field->board[to] = tv->field->squareIsFree; - // store predecessor - tv->storePredecessor(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, amountOfPred, predVars); + // store predecessor + tv->storePredecessor(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, amountOfPred, predVars); - // undo move - tv->field->board[to] = tv->field->board[from]; - tv->field->board[from] = tv->field->squareIsFree; + // undo move + tv->field->board[to] = tv->field->board[from]; + tv->field->board[from] = tv->field->squareIsFree; - if (millWasClosed) - { - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; - tv->field->stoneMustBeRemoved = 1; - } - else - { - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; - i = numberOfMillsCurrentPlayer; - numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; - numberOfMillsOpponentPlayer = i; - } - } - } - } - } - } + if (millWasClosed) { + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; + tv->field->stoneMustBeRemoved = 1; + } else { + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[to]; + i = numberOfMillsCurrentPlayer; + numberOfMillsCurrentPlayer = numberOfMillsOpponentPlayer; + numberOfMillsOpponentPlayer = i; + } + } + } + } + } + } - // was a stone removed ? - if (tv->field->curPlayer->numStones < 9 && tv->field->curPlayer->numStonesMissing > 0 && tv->field->stoneMustBeRemoved == 0) - { + // was a stone removed ? + if (tv->field->curPlayer->numStones < 9 && tv->field->curPlayer->numStonesMissing > 0 && tv->field->stoneMustBeRemoved == 0) { - // has opponent player a closed mill ? - if (numberOfMillsOpponentPlayer) - { + // has opponent player a closed mill ? + if (numberOfMillsOpponentPlayer) { - // from each free position the opponent could have removed a stone from the current player - for (from = 0; from < tv->field->size; from++) - { + // from each free position the opponent could have removed a stone from the current player + for (from = 0; from < tv->field->size; from++) { - // square free? - if (tv->field->board[from] == tv->field->squareIsFree) - { + // square free? + if (tv->field->board[from] == tv->field->squareIsFree) { - // stone mustn't be part of mill - if ((!(tv->field->board[tv->field->neighbour[from][0][0]] == tv->field->curPlayer->id && tv->field->board[tv->field->neighbour[from][0][1]] == tv->field->curPlayer->id)) && (!(tv->field->board[tv->field->neighbour[from][1][0]] == tv->field->curPlayer->id && tv->field->board[tv->field->neighbour[from][1][1]] == tv->field->curPlayer->id))) - { + // stone mustn't be part of mill + if ((!(tv->field->board[tv->field->neighbour[from][0][0]] == tv->field->curPlayer->id && tv->field->board[tv->field->neighbour[from][0][1]] == tv->field->curPlayer->id)) && (!(tv->field->board[tv->field->neighbour[from][1][0]] == tv->field->curPlayer->id && tv->field->board[tv->field->neighbour[from][1][1]] == tv->field->curPlayer->id))) { - // put back stone - tv->field->stoneMustBeRemoved = 1; - tv->field->board[from] = tv->field->curPlayer->id; - tv->field->curPlayer->numStones++; - tv->field->curPlayer->numStonesMissing--; + // put back stone + tv->field->stoneMustBeRemoved = 1; + tv->field->board[from] = tv->field->curPlayer->id; + tv->field->curPlayer->numStones++; + tv->field->curPlayer->numStonesMissing--; - // it was an opponent move - predVars[*amountOfPred].playerToMoveChanged = true; - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; + // it was an opponent move + predVars[*amountOfPred].playerToMoveChanged = true; + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; - // store predecessor - tv->storePredecessor(numberOfMillsOpponentPlayer, numberOfMillsCurrentPlayer, amountOfPred, predVars); + // store predecessor + tv->storePredecessor(numberOfMillsOpponentPlayer, numberOfMillsCurrentPlayer, amountOfPred, predVars); - tmpPlayer = tv->field->curPlayer; - tv->field->curPlayer = tv->field->oppPlayer; - tv->field->oppPlayer = tmpPlayer; + tmpPlayer = tv->field->curPlayer; + tv->field->curPlayer = tv->field->oppPlayer; + tv->field->oppPlayer = tmpPlayer; - // remove stone again - tv->field->stoneMustBeRemoved = 0; - tv->field->board[from] = tv->field->squareIsFree; - tv->field->curPlayer->numStones--; - tv->field->curPlayer->numStonesMissing++; - } - } - } - } - } + // remove stone again + tv->field->stoneMustBeRemoved = 0; + tv->field->board[from] = tv->field->squareIsFree; + tv->field->curPlayer->numStones--; + tv->field->curPlayer->numStonesMissing++; + } + } + } + } + } } //----------------------------------------------------------------------------- @@ -2623,94 +2409,87 @@ void PerfectAI::getPredecessors(unsigned int threadNo, unsigned int *amountOfPre //----------------------------------------------------------------------------- bool PerfectAI::checkMoveAndSetSituation() { - // locals - bool aStoneCanBeRemovedFromCurPlayer; - unsigned int numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer; - unsigned int stateNum, layerNum, curMove, i; - unsigned int *idPossibility; - unsigned int numPossibilities; - bool isOpponentLevel; - void *pPossibilities; - void *pBackup; - unsigned int threadNo = 0; - ThreadVars *tv = &threadVars[threadNo]; + // locals + bool aStoneCanBeRemovedFromCurPlayer; + unsigned int numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer; + unsigned int stateNum, layerNum, curMove, i; + unsigned int *idPossibility; + unsigned int numPossibilities; + bool isOpponentLevel; + void *pPossibilities; + void *pBackup; + unsigned int threadNo = 0; + ThreadVars *tv = &threadVars[threadNo]; - // output - cout << endl - << "checkMoveAndSetSituation()" << endl; + // output + cout << endl + << "checkMoveAndSetSituation()" << endl; - // test if each successor from getPossibilities() leads to the original state using getPredecessors() - for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) - { + // test if each successor from getPossibilities() leads to the original state using getPredecessors() + for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) { - // generate random state - cout << endl - << "TESTING LAYER: " << layerNum; - if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) - continue; + // generate random state + cout << endl + << "TESTING LAYER: " << layerNum; + if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) + continue; - // test each state of layer - for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) - { + // test each state of layer + for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) { - // set situation - if (stateNum % OUTPUT_EVERY_N_STATES == 0) - cout << endl - << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; - if (!setSituation(threadNo, layerNum, stateNum)) - continue; + // set situation + if (stateNum % OUTPUT_EVERY_N_STATES == 0) + cout << endl + << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; + if (!setSituation(threadNo, layerNum, stateNum)) + continue; - // get all possible moves - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + // get all possible moves + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - // go to each successor state - for (curMove = 0; curMove < numPossibilities; curMove++) - { + // go to each successor state + for (curMove = 0; curMove < numPossibilities; curMove++) { - // move - move(threadNo, idPossibility[curMove], isOpponentLevel, &pBackup, pPossibilities); + // move + move(threadNo, idPossibility[curMove], isOpponentLevel, &pBackup, pPossibilities); - // count completed mills - numberOfMillsCurrentPlayer = 0; - numberOfMillsOpponentPlayer = 0; - for (i = 0; i < fieldStruct::size; i++) - { - if (tv->field->board[i] == tv->field->curPlayer->id) - numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; - else - numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; - } - numberOfMillsCurrentPlayer /= 3; - numberOfMillsOpponentPlayer /= 3; + // count completed mills + numberOfMillsCurrentPlayer = 0; + numberOfMillsOpponentPlayer = 0; + for (i = 0; i < fieldStruct::size; i++) { + if (tv->field->board[i] == tv->field->curPlayer->id) + numberOfMillsCurrentPlayer += tv->field->stonePartOfMill[i]; + else + numberOfMillsOpponentPlayer += tv->field->stonePartOfMill[i]; + } + numberOfMillsCurrentPlayer /= 3; + numberOfMillsOpponentPlayer /= 3; - // precalc aStoneCanBeRemovedFromCurPlayer - for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) - { - if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) - { - aStoneCanBeRemovedFromCurPlayer = true; - break; - } - } + // precalc aStoneCanBeRemovedFromCurPlayer + for (aStoneCanBeRemovedFromCurPlayer = false, i = 0; i < tv->field->size; i++) { + if (tv->field->stonePartOfMill[i] == 0 && tv->field->board[i] == tv->field->curPlayer->id) { + aStoneCanBeRemovedFromCurPlayer = true; + break; + } + } - // - if (tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer) == false) - { - cout << endl - << "ERROR: STATE " << stateNum << " REACHED WITH move(), BUT IS INVALID!"; - //return false; - } + // + if (tv->fieldIntegrityOK(numberOfMillsCurrentPlayer, numberOfMillsOpponentPlayer, aStoneCanBeRemovedFromCurPlayer) == false) { + cout << endl + << "ERROR: STATE " << stateNum << " REACHED WITH move(), BUT IS INVALID!"; + //return false; + } - // undo move - undo(threadNo, idPossibility[curMove], isOpponentLevel, pBackup, pPossibilities); - } - } - cout << endl - << "LAYER OK: " << layerNum << endl; - } + // undo move + undo(threadNo, idPossibility[curMove], isOpponentLevel, pBackup, pPossibilities); + } + } + cout << endl + << "LAYER OK: " << layerNum << endl; + } - // free mem - return true; + // free mem + return true; } //----------------------------------------------------------------------------- @@ -2719,90 +2498,85 @@ bool PerfectAI::checkMoveAndSetSituation() //----------------------------------------------------------------------------- bool PerfectAI::checkGetPossThanGetPred() { - // locals - unsigned int stateNum, layerNum, i, j; - unsigned int *idPossibility; - unsigned int numPossibilities; - unsigned int amountOfPred; - bool isOpponentLevel; - void *pPossibilities; - void *pBackup; - RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; - unsigned int threadNo = 0; - ThreadVars *tv = &threadVars[threadNo]; + // locals + unsigned int stateNum, layerNum, i, j; + unsigned int *idPossibility; + unsigned int numPossibilities; + unsigned int amountOfPred; + bool isOpponentLevel; + void *pPossibilities; + void *pBackup; + RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; + unsigned int threadNo = 0; + ThreadVars *tv = &threadVars[threadNo]; - // test if each successor from getPossibilities() leads to the original state using getPredecessors() - for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) - { + // test if each successor from getPossibilities() leads to the original state using getPredecessors() + for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) { - // generate random state - cout << endl - << "TESTING LAYER: " << layerNum; - if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) - continue; + // generate random state + cout << endl + << "TESTING LAYER: " << layerNum; + if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) + continue; - // test each state of layer - for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) - { + // test each state of layer + for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) { - // set situation - if (stateNum % 10000 == 0) - cout << endl - << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; - if (!setSituation(threadNo, layerNum, stateNum)) - continue; + // set situation + if (stateNum % 10000 == 0) + cout << endl + << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; + if (!setSituation(threadNo, layerNum, stateNum)) + continue; - // get all possible moves - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + // get all possible moves + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - // go to each successor state - for (i = 0; i < numPossibilities; i++) - { + // go to each successor state + for (i = 0; i < numPossibilities; i++) { - // move - move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); + // move + move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); - // get predecessors1 - getPredecessors(threadNo, &amountOfPred, predVars); + // get predecessors1 + getPredecessors(threadNo, &amountOfPred, predVars); - // does it match ? - for (j = 0; j < amountOfPred; j++) - { - if (predVars[j].predStateNumbers == stateNum && predVars[j].predLayerNumbers == layerNum) - break; - } + // does it match ? + for (j = 0; j < amountOfPred; j++) { + if (predVars[j].predStateNumbers == stateNum && predVars[j].predLayerNumbers == layerNum) + break; + } - // error? - if (j == amountOfPred) - { + // error? + if (j == amountOfPred) { - cout << endl - << "ERROR: STATE " << stateNum << " NOT FOUND IN PREDECESSOR LIST"; - return false; + cout << endl + << "ERROR: STATE " << stateNum << " NOT FOUND IN PREDECESSOR LIST"; + return false; - // perform several commands to see in debug mode where the error occurs - undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); - setSituation(threadNo, layerNum, stateNum); - cout << "current state" << endl; - cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; - printBoard(threadNo, 0); - move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); - cout << "successor" << endl; - printBoard(threadNo, 0); - getPredecessors(threadNo, &amountOfPred, predVars); - getPredecessors(threadNo, &amountOfPred, predVars); - } + // perform several commands to see in debug mode where the error occurs + undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); + setSituation(threadNo, layerNum, stateNum); + cout << "current state" << endl; + cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; + printBoard(threadNo, 0); + move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); + cout << "successor" << endl; + printBoard(threadNo, 0); + getPredecessors(threadNo, &amountOfPred, predVars); + getPredecessors(threadNo, &amountOfPred, predVars); + } - // undo move - undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); - } - } - cout << endl - << "LAYER OK: " << layerNum << endl; - } + // undo move + undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); + } + } + cout << endl + << "LAYER OK: " << layerNum << endl; + } - // everything fine - return true; + // everything fine + return true; } //----------------------------------------------------------------------------- @@ -2811,179 +2585,170 @@ bool PerfectAI::checkGetPossThanGetPred() //----------------------------------------------------------------------------- bool PerfectAI::checkGetPredThanGetPoss() { - // locals - unsigned int threadNo = 0; - ThreadVars *tv = &threadVars[threadNo]; - unsigned int stateNum, layerNum, i, j, k; - unsigned int stateNumB, layerNumB; - unsigned int *idPossibility; - unsigned int numPossibilities; - unsigned int amountOfPred; - bool isOpponentLevel; - void *pPossibilities; - void *pBackup; - int symField[fieldStruct::size]; - RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; + // locals + unsigned int threadNo = 0; + ThreadVars *tv = &threadVars[threadNo]; + unsigned int stateNum, layerNum, i, j, k; + unsigned int stateNumB, layerNumB; + unsigned int *idPossibility; + unsigned int numPossibilities; + unsigned int amountOfPred; + bool isOpponentLevel; + void *pPossibilities; + void *pBackup; + int symField[fieldStruct::size]; + RetroAnalysisPredVars predVars[MAX_NUM_PREDECESSORS]; - // test if each predecessor from getPredecessors() leads to the original state using getPossibilities() - for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) - { + // test if each predecessor from getPredecessors() leads to the original state using getPossibilities() + for (layerNum = 0; layerNum < NUM_LAYERS; layerNum++) { - // generate random state - cout << endl - << "TESTING LAYER: " << layerNum; - if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) - continue; + // generate random state + cout << endl + << "TESTING LAYER: " << layerNum; + if (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex == 0) + continue; - // test each state of layer - for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) - { + // test each state of layer + for (stateNum = 0; stateNum < (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; stateNum++) { - // set situation - if (stateNum % 10000000 == 0) - cout << endl - << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; - if (!setSituation(threadNo, layerNum, stateNum)) - continue; + // set situation + if (stateNum % 10000000 == 0) + cout << endl + << "TESTING STATE " << stateNum << " OF " << (layer[layerNum].subLayer[layer[layerNum].numSubLayers - 1].maxIndex + 1) * MAX_NUM_STONES_REMOVED_MINUS_1; + if (!setSituation(threadNo, layerNum, stateNum)) + continue; - // get predecessors - getPredecessors(threadNo, &amountOfPred, predVars); + // get predecessors + getPredecessors(threadNo, &amountOfPred, predVars); - // test each returned predecessor - for (j = 0; j < amountOfPred; j++) - { + // test each returned predecessor + for (j = 0; j < amountOfPred; j++) { - // set situation - if (!setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers)) - { + // set situation + if (!setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers)) { - cout << endl - << "ERROR SETTING SITUATION"; - return false; + cout << endl + << "ERROR SETTING SITUATION"; + return false; - // perform several commands to see in debug mode where the error occurs - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->board[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->stonePartOfMill[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); - cout << "predecessor" << endl; - cout << " layerNum: " << predVars[j].predLayerNumbers << "\tstateNum: " << predVars[j].predStateNumbers << endl; - printBoard(threadNo, 0); - if (predVars[j].playerToMoveChanged) - { - k = tv->field->curPlayer->id; - tv->field->curPlayer->id = tv->field->oppPlayer->id; - tv->field->oppPlayer->id = k; - for (k = 0; k < tv->field->size; k++) - tv->field->board[k] = -1 * tv->field->board[k]; - } - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - setSituation(threadNo, layerNum, stateNum); - cout << "current state" << endl; - cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; - printBoard(threadNo, 0); - getPredecessors(threadNo, &amountOfPred, predVars); - } + // perform several commands to see in debug mode where the error occurs + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->board[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->stonePartOfMill[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); + cout << "predecessor" << endl; + cout << " layerNum: " << predVars[j].predLayerNumbers << "\tstateNum: " << predVars[j].predStateNumbers << endl; + printBoard(threadNo, 0); + if (predVars[j].playerToMoveChanged) { + k = tv->field->curPlayer->id; + tv->field->curPlayer->id = tv->field->oppPlayer->id; + tv->field->oppPlayer->id = k; + for (k = 0; k < tv->field->size; k++) + tv->field->board[k] = -1 * tv->field->board[k]; + } + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + setSituation(threadNo, layerNum, stateNum); + cout << "current state" << endl; + cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; + printBoard(threadNo, 0); + getPredecessors(threadNo, &amountOfPred, predVars); + } - // regard used symmetry operation - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->board[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->stonePartOfMill[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); - if (predVars[j].playerToMoveChanged) - { - k = tv->field->curPlayer->id; - tv->field->curPlayer->id = tv->field->oppPlayer->id; - tv->field->oppPlayer->id = k; - for (k = 0; k < tv->field->size; k++) - tv->field->board[k] = -1 * tv->field->board[k]; - } + // regard used symmetry operation + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->board[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->stonePartOfMill[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); + if (predVars[j].playerToMoveChanged) { + k = tv->field->curPlayer->id; + tv->field->curPlayer->id = tv->field->oppPlayer->id; + tv->field->oppPlayer->id = k; + for (k = 0; k < tv->field->size; k++) + tv->field->board[k] = -1 * tv->field->board[k]; + } - // get all possible moves - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + // get all possible moves + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - // go to each successor state - for (i = 0; i < numPossibilities; i++) - { + // go to each successor state + for (i = 0; i < numPossibilities; i++) { - // move - move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); + // move + move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities); - // get numbers - getLayerAndStateNumber(threadNo, layerNumB, stateNumB); + // get numbers + getLayerAndStateNumber(threadNo, layerNumB, stateNumB); - // does states match ? - if (stateNum == stateNumB && layerNum == layerNumB) - break; + // does states match ? + if (stateNum == stateNumB && layerNum == layerNumB) + break; - // undo move - undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); - } + // undo move + undo(threadNo, idPossibility[i], isOpponentLevel, pBackup, pPossibilities); + } - // error? - if (i == numPossibilities) - { + // error? + if (i == numPossibilities) { - cout << endl - << "ERROR: Not all predecessors lead to state " << stateNum << " calling move()" << endl; - //return false; + cout << endl + << "ERROR: Not all predecessors lead to state " << stateNum << " calling move()" << endl; + //return false; - // perform several commands to see in debug mode where the error occurs - setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->board[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->stonePartOfMill[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); - cout << "predecessor" << endl; - cout << " layerNum: " << predVars[j].predLayerNumbers << "\tstateNum: " << predVars[j].predStateNumbers << endl; - printBoard(threadNo, 0); - if (predVars[j].playerToMoveChanged) - { - k = tv->field->curPlayer->id; - tv->field->curPlayer->id = tv->field->oppPlayer->id; - tv->field->oppPlayer->id = k; - for (k = 0; k < tv->field->size; k++) - tv->field->board[k] = -1 * tv->field->board[k]; - } - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - setSituation(threadNo, layerNum, stateNum); - cout << "current state" << endl; - cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; - printBoard(threadNo, 0); - getPredecessors(threadNo, &amountOfPred, predVars); + // perform several commands to see in debug mode where the error occurs + setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->board[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->stonePartOfMill[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); + cout << "predecessor" << endl; + cout << " layerNum: " << predVars[j].predLayerNumbers << "\tstateNum: " << predVars[j].predStateNumbers << endl; + printBoard(threadNo, 0); + if (predVars[j].playerToMoveChanged) { + k = tv->field->curPlayer->id; + tv->field->curPlayer->id = tv->field->oppPlayer->id; + tv->field->oppPlayer->id = k; + for (k = 0; k < tv->field->size; k++) + tv->field->board[k] = -1 * tv->field->board[k]; + } + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + setSituation(threadNo, layerNum, stateNum); + cout << "current state" << endl; + cout << " layerNum: " << layerNum << "\tstateNum: " << stateNum << endl; + printBoard(threadNo, 0); + getPredecessors(threadNo, &amountOfPred, predVars); - k = tv->field->curPlayer->id; - tv->field->curPlayer->id = tv->field->oppPlayer->id; - tv->field->oppPlayer->id = k; - for (k = 0; k < tv->field->size; k++) - tv->field->board[k] = -1 * tv->field->board[k]; - setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->board[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); - for (k = 0; k < tv->field->size; k++) - symField[k] = tv->field->stonePartOfMill[k]; - applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); - printBoard(threadNo, 0); - idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); - move(threadNo, idPossibility[1], isOpponentLevel, &pBackup, pPossibilities); - printBoard(threadNo, 0); - getLayerAndStateNumber(threadNo, layerNumB, stateNumB); - } - } - } - cout << endl - << "LAYER OK: " << layerNum << endl; - } + k = tv->field->curPlayer->id; + tv->field->curPlayer->id = tv->field->oppPlayer->id; + tv->field->oppPlayer->id = k; + for (k = 0; k < tv->field->size; k++) + tv->field->board[k] = -1 * tv->field->board[k]; + setSituation(threadNo, predVars[j].predLayerNumbers, predVars[j].predStateNumbers); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->board[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->board); + for (k = 0; k < tv->field->size; k++) + symField[k] = tv->field->stonePartOfMill[k]; + applySymmetrieOperationOnField(reverseSymOperation[predVars[j].predSymOperation], (unsigned int *)symField, (unsigned int *)tv->field->stonePartOfMill); + printBoard(threadNo, 0); + idPossibility = getPossibilities(threadNo, &numPossibilities, &isOpponentLevel, &pPossibilities); + move(threadNo, idPossibility[1], isOpponentLevel, &pBackup, pPossibilities); + printBoard(threadNo, 0); + getLayerAndStateNumber(threadNo, layerNumB, stateNumB); + } + } + } + cout << endl + << "LAYER OK: " << layerNum << endl; + } - // free mem - return true; + // free mem + return true; } /*** To Do's *************************************** diff --git a/src/perfect/perfectAI.h b/src/perfect/perfectAI.h index ace86da6..73586f16 100644 --- a/src/perfect/perfectAI.h +++ b/src/perfect/perfectAI.h @@ -1,9 +1,9 @@ /*********************************************************************\ - PerfectAI.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + PerfectAI.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef PERFEKT_AI_H @@ -78,166 +78,166 @@ class PerfectAI : public MillAI, public MiniMax { protected: - // structs - struct SubLayer - { - unsigned int minIndex; - unsigned int maxIndex; - unsigned int numWhiteStonesGroupCD, numBlackStonesGroupCD; - unsigned int numWhiteStonesGroupAB, numBlackStonesGroupAB; - }; + // structs + struct SubLayer + { + unsigned int minIndex; + unsigned int maxIndex; + unsigned int numWhiteStonesGroupCD, numBlackStonesGroupCD; + unsigned int numWhiteStonesGroupAB, numBlackStonesGroupAB; + }; - struct Layer - { - unsigned int numWhiteStones; - unsigned int numBlackStones; - unsigned int numSubLayers; - unsigned int subLayerIndexAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - unsigned int subLayerIndexCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - SubLayer subLayer[MAX_NUM_SUB_LAYERS]; - }; + struct Layer + { + unsigned int numWhiteStones; + unsigned int numBlackStones; + unsigned int numSubLayers; + unsigned int subLayerIndexAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + unsigned int subLayerIndexCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + SubLayer subLayer[MAX_NUM_SUB_LAYERS]; + }; - struct Possibility - { - unsigned int from[MAX_NUM_POS_MOVES]; - unsigned int to[MAX_NUM_POS_MOVES]; - }; + struct Possibility + { + unsigned int from[MAX_NUM_POS_MOVES]; + unsigned int to[MAX_NUM_POS_MOVES]; + }; - struct Backup - { - float floatValue; - TwoBit shortValue; - bool gameHasFinished; - bool settingPhase; - int fieldFrom, fieldTo; // value of board - unsigned int from, to; // index of board - unsigned int curNumStones, oppNumStones; - unsigned int curPosMoves, oppPosMoves; - unsigned int curMissStones, oppMissStones; - unsigned int stonesSet; - unsigned int stoneMustBeRemoved; - unsigned int stonePartOfMill[fieldStruct::size]; - Player *curPlayer, *oppPlayer; - }; + struct Backup + { + float floatValue; + TwoBit shortValue; + bool gameHasFinished; + bool settingPhase; + int fieldFrom, fieldTo; // value of board + unsigned int from, to; // index of board + unsigned int curNumStones, oppNumStones; + unsigned int curPosMoves, oppPosMoves; + unsigned int curMissStones, oppMissStones; + unsigned int stonesSet; + unsigned int stoneMustBeRemoved; + unsigned int stonePartOfMill[fieldStruct::size]; + Player *curPlayer, *oppPlayer; + }; - // preCalcedVars.dat - struct PreCalcedVarsFileHeader - { - unsigned int sizeInBytes; - }; + // preCalcedVars.dat + struct PreCalcedVarsFileHeader + { + unsigned int sizeInBytes; + }; - // constant variables for state addressing in the database - Layer layer[NUM_LAYERS]; // the layers - unsigned int layerIndex[2][NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; // indices of layer [moving/setting phase][number of white stones][number of black stones] - unsigned int anzahlStellungenCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - unsigned int anzahlStellungenAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - unsigned int indexAB[MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B]; - unsigned int indexCD[MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D]; - unsigned char symmetryOperationCD[MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D]; // index of symmetry operation used to get from the original state to the current one - unsigned int powerOfThree[numSquaresGroupC + numSquaresGroupD]; // 3^0, 3^1, 3^2, ... - unsigned int symmetryOperationTable[NUM_SYM_OPERATIONS][fieldStruct::size]; // Matrix used for application of the symmetry operations - unsigned int *originalStateCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - unsigned int *originalStateAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; - unsigned int reverseSymOperation[NUM_SYM_OPERATIONS]; // index of the reverse symmetry operation - unsigned int concSymOperation[NUM_SYM_OPERATIONS][NUM_SYM_OPERATIONS]; // symmetry operation, which is identical to applying those two in the index - unsigned int mOverN[fieldStruct::size + 1][fieldStruct::size + 1]; // m over n - unsigned char valueOfMove[fieldStruct::size * fieldStruct::size]; // contains the value of the situation, which will be achieved by that move - unsigned short plyInfoForOutput[fieldStruct::size * fieldStruct::size]; // contains the value of the situation, which will be achieved by that move - unsigned int incidencesValuesSubMoves[fieldStruct::size * fieldStruct::size][4]; // contains the number of ... - unsigned int symmetricStateNumberArray[NUM_SYM_OPERATIONS]; // array for state numbers - string databaseDirectory; // directory containing the database files + // constant variables for state addressing in the database + Layer layer[NUM_LAYERS]; // the layers + unsigned int layerIndex[2][NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; // indices of layer [moving/setting phase][number of white stones][number of black stones] + unsigned int anzahlStellungenCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + unsigned int anzahlStellungenAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + unsigned int indexAB[MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B]; + unsigned int indexCD[MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D]; + unsigned char symmetryOperationCD[MAX_ANZ_STELLUNGEN_C * MAX_ANZ_STELLUNGEN_D]; // index of symmetry operation used to get from the original state to the current one + unsigned int powerOfThree[numSquaresGroupC + numSquaresGroupD]; // 3^0, 3^1, 3^2, ... + unsigned int symmetryOperationTable[NUM_SYM_OPERATIONS][fieldStruct::size]; // Matrix used for application of the symmetry operations + unsigned int *originalStateCD[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + unsigned int *originalStateAB[NUM_STONES_PER_PLAYER_PLUS_ONE][NUM_STONES_PER_PLAYER_PLUS_ONE]; + unsigned int reverseSymOperation[NUM_SYM_OPERATIONS]; // index of the reverse symmetry operation + unsigned int concSymOperation[NUM_SYM_OPERATIONS][NUM_SYM_OPERATIONS]; // symmetry operation, which is identical to applying those two in the index + unsigned int mOverN[fieldStruct::size + 1][fieldStruct::size + 1]; // m over n + unsigned char valueOfMove[fieldStruct::size * fieldStruct::size]; // contains the value of the situation, which will be achieved by that move + unsigned short plyInfoForOutput[fieldStruct::size * fieldStruct::size]; // contains the value of the situation, which will be achieved by that move + unsigned int incidencesValuesSubMoves[fieldStruct::size * fieldStruct::size][4]; // contains the number of ... + unsigned int symmetricStateNumberArray[NUM_SYM_OPERATIONS]; // array for state numbers + string databaseDirectory; // directory containing the database files - // Variables used individually by each single thread - class ThreadVars - { - public: - fieldStruct *field; // pointer of the current board [changed by move()] - float floatValue; // value of current situation for board->currentPlayer - TwoBit shortValue; // '' - bool gameHasFinished; // someone has won or current board is full - int ownId; // id of the player who called the play()-function - unsigned int curSearchDepth; // current level - unsigned int depthOfFullTree; // search depth where the whole tree is explored - unsigned int *idPossibilities; // returned pointer of getPossibilities()-function - Backup *oldStates; // for undo()-function - Possibility *possibilities; // for getPossNormalMove()-function - PerfectAI *parent; // + // Variables used individually by each single thread + class ThreadVars + { + public: + fieldStruct *field; // pointer of the current board [changed by move()] + float floatValue; // value of current situation for board->currentPlayer + TwoBit shortValue; // '' + bool gameHasFinished; // someone has won or current board is full + int ownId; // id of the player who called the play()-function + unsigned int curSearchDepth; // current level + unsigned int depthOfFullTree; // search depth where the whole tree is explored + unsigned int *idPossibilities; // returned pointer of getPossibilities()-function + Backup *oldStates; // for undo()-function + Possibility *possibilities; // for getPossNormalMove()-function + PerfectAI *parent; // - // constructor - ThreadVars(); + // constructor + ThreadVars(); - // Functions - unsigned int *getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities); - unsigned int *getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities); - unsigned int *getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities); + // Functions + unsigned int *getPossSettingPhase(unsigned int *numPossibilities, void **pPossibilities); + unsigned int *getPossNormalMove(unsigned int *numPossibilities, void **pPossibilities); + unsigned int *getPossStoneRemove(unsigned int *numPossibilities, void **pPossibilities); - // move functions - inline void updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone); - inline void updateWarning(unsigned int firstStone, unsigned int secondStone); - inline void setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree); - inline void removeStone(unsigned int from, Backup *backup); - inline void setStone(unsigned int to, Backup *backup); - inline void normalMove(unsigned int from, unsigned int to, Backup *backup); + // move functions + inline void updatePossibleMoves(unsigned int stone, Player *stoneOwner, bool stoneRemoved, unsigned int ignoreStone); + inline void updateWarning(unsigned int firstStone, unsigned int secondStone); + inline void setWarning(unsigned int stoneOne, unsigned int stoneTwo, unsigned int stoneThree); + inline void removeStone(unsigned int from, Backup *backup); + inline void setStone(unsigned int to, Backup *backup); + inline void normalMove(unsigned int from, unsigned int to, Backup *backup); - // database functions - unsigned int getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber); - void setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour); - bool fieldIntegrityOK(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, bool aStoneCanBeRemovedFromCurPlayer); - void calcPossibleMoves(Player *player); - void storePredecessor(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars); - }; - ThreadVars *threadVars; + // database functions + unsigned int getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber); + void setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour); + bool fieldIntegrityOK(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, bool aStoneCanBeRemovedFromCurPlayer); + void calcPossibleMoves(Player *player); + void storePredecessor(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars); + }; + ThreadVars *threadVars; - // database functions - unsigned int getNumberOfLayers(); - unsigned int getNumberOfKnotsInLayer(unsigned int layerNum); - long long mOverN_Function(unsigned int m, unsigned int n); - void applySymmetrieOperationOnField(unsigned char symmetryOperationNumber, unsigned int *sourceField, unsigned int *destField); - bool isSymOperationInvariantOnGroupCD(unsigned int symmetryOperation, int *theField); - bool shallRetroAnalysisBeUsed(unsigned int layerNum); - void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers); - void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars); - bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber); - unsigned int getLayerNumber(unsigned int threadNo); - unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber); + // database functions + unsigned int getNumberOfLayers(); + unsigned int getNumberOfKnotsInLayer(unsigned int layerNum); + long long mOverN_Function(unsigned int m, unsigned int n); + void applySymmetrieOperationOnField(unsigned char symmetryOperationNumber, unsigned int *sourceField, unsigned int *destField); + bool isSymOperationInvariantOnGroupCD(unsigned int symmetryOperation, int *theField); + bool shallRetroAnalysisBeUsed(unsigned int layerNum); + void getSuccLayers(unsigned int layerNum, unsigned int *amountOfSuccLayers, unsigned int *succLayers); + void getPredecessors(unsigned int threadNo, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars); + bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber); + unsigned int getLayerNumber(unsigned int threadNo); + unsigned int getLayerAndStateNumber(unsigned int threadNo, unsigned int &layerNum, unsigned int &stateNumber); - // integrity test functions - bool checkMoveAndSetSituation(); - bool checkGetPossThanGetPred(); - bool checkGetPredThanGetPoss(); + // integrity test functions + bool checkMoveAndSetSituation(); + bool checkGetPossThanGetPred(); + bool checkGetPredThanGetPoss(); - // Virtual Functions - void prepareBestChoiceCalculation(); - void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue); - void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel); - bool getOpponentLevel(unsigned int threadNo); - void deletePossibilities(unsigned int threadNo, void *pPossibilities); - unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities); - void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities); - void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities); - void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities); - void storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, unsigned char value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo); - void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers); - void printBoard(unsigned int threadNo, unsigned char value); - string getOutputInformation(unsigned int layerNum); - unsigned int getPartnerLayer(unsigned int layerNum); - void prepareDatabaseCalculation(); - void wrapUpDatabaseCalculation(bool calculationAborted); + // Virtual Functions + void prepareBestChoiceCalculation(); + void getValueOfSituation(unsigned int threadNo, float &floatValue, TwoBit &shortValue); + void setOpponentLevel(unsigned int threadNo, bool isOpponentLevel); + bool getOpponentLevel(unsigned int threadNo); + void deletePossibilities(unsigned int threadNo, void *pPossibilities); + unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities); + void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities); + void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities); + void printMoveInformation(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities); + void storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, unsigned char value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo); + void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers); + void printBoard(unsigned int threadNo, unsigned char value); + string getOutputInformation(unsigned int layerNum); + unsigned int getPartnerLayer(unsigned int layerNum); + void prepareDatabaseCalculation(); + void wrapUpDatabaseCalculation(bool calculationAborted); public: - // Constructor / destructor - PerfectAI(const char *directory); - ~PerfectAI(); + // Constructor / destructor + PerfectAI(const char *directory); + ~PerfectAI(); - // Functions - bool setDatabasePath(const char *directory); - void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); - void getValueOfMoves(unsigned char *moveValue, unsigned int *freqValuesSubMoves, PlyInfoVarType *plyInfo, unsigned int *moveQuality, unsigned char &knotValue, PlyInfoVarType &bestAmountOfPlies); - void getField(unsigned int layerNum, unsigned int stateNumber, fieldStruct *field, bool *gameHasFinished); - void getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber); + // Functions + bool setDatabasePath(const char *directory); + void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); + void getValueOfMoves(unsigned char *moveValue, unsigned int *freqValuesSubMoves, PlyInfoVarType *plyInfo, unsigned int *moveQuality, unsigned char &knotValue, PlyInfoVarType &bestAmountOfPlies); + void getField(unsigned int layerNum, unsigned int stateNumber, fieldStruct *field, bool *gameHasFinished); + void getLayerAndStateNumber(unsigned int &layerNum, unsigned int &stateNumber); - // Testing functions - bool testLayers(unsigned int startTestFromLayer, unsigned int endTestAtLayer); + // Testing functions + bool testLayers(unsigned int startTestFromLayer, unsigned int endTestAtLayer); }; #endif \ No newline at end of file diff --git a/src/perfect/position.cpp b/src/perfect/position.cpp index c0271591..0aaa86eb 100644 --- a/src/perfect/position.cpp +++ b/src/perfect/position.cpp @@ -1,9 +1,9 @@ /********************************************************************* - Position.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + Position.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "position.h" @@ -14,16 +14,16 @@ //----------------------------------------------------------------------------- Position::Position() { - srand((unsigned)time(nullptr)); + srand((unsigned)time(nullptr)); - moveLogFrom = nullptr; - moveLogTo = nullptr; - playerOneAI = nullptr; - playerTwoAI = nullptr; - movesDone = 0; + moveLogFrom = nullptr; + moveLogTo = nullptr; + playerOneAI = nullptr; + playerTwoAI = nullptr; + movesDone = 0; - field.createBoard(); - initialField.createBoard(); + field.createBoard(); + initialField.createBoard(); } //----------------------------------------------------------------------------- @@ -32,7 +32,7 @@ Position::Position() //----------------------------------------------------------------------------- Position::~Position() { - exit(); + exit(); } //----------------------------------------------------------------------------- @@ -41,11 +41,11 @@ Position::~Position() //----------------------------------------------------------------------------- void Position::exit() { - SAFE_DELETE_ARRAY(moveLogFrom); - SAFE_DELETE_ARRAY(moveLogTo); + SAFE_DELETE_ARRAY(moveLogFrom); + SAFE_DELETE_ARRAY(moveLogTo); - field.deleteBoard(); - initialField.deleteBoard(); + field.deleteBoard(); + initialField.deleteBoard(); } //----------------------------------------------------------------------------- @@ -54,34 +54,31 @@ void Position::exit() //----------------------------------------------------------------------------- void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer) { - // free mem - exit(); + // free mem + exit(); - // create arrays - field.createBoard(); - initialField.createBoard(); + // create arrays + field.createBoard(); + initialField.createBoard(); - // calc beginning player - if (currentPlayer == field.playerOne || currentPlayer == field.playerTwo) - { - beginningPlayer = currentPlayer; - } - else - { - beginningPlayer = (rand() % 2) ? field.playerOne : field.playerTwo; - } - field.curPlayer->id = beginningPlayer; - field.oppPlayer->id = (field.curPlayer->id == field.playerTwo) ? field.playerOne : field.playerTwo; + // calc beginning player + if (currentPlayer == field.playerOne || currentPlayer == field.playerTwo) { + beginningPlayer = currentPlayer; + } else { + beginningPlayer = (rand() % 2) ? field.playerOne : field.playerTwo; + } + field.curPlayer->id = beginningPlayer; + field.oppPlayer->id = (field.curPlayer->id == field.playerTwo) ? field.playerOne : field.playerTwo; - winner = 0; - movesDone = 0; - playerOneAI = firstPlayerAI; - playerTwoAI = secondPlayerAI; - moveLogFrom = new unsigned int[MAX_NUM_MOVES]; - moveLogTo = new unsigned int[MAX_NUM_MOVES]; + winner = 0; + movesDone = 0; + playerOneAI = firstPlayerAI; + playerTwoAI = secondPlayerAI; + moveLogFrom = new unsigned int[MAX_NUM_MOVES]; + moveLogTo = new unsigned int[MAX_NUM_MOVES]; - // remember initialField - field.copyBoard(&initialField); + // remember initialField + field.copyBoard(&initialField); } //----------------------------------------------------------------------------- @@ -90,11 +87,11 @@ void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int c //----------------------------------------------------------------------------- bool Position::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer, bool settingPhase) { - beginNewGame(firstPlayerAI, secondPlayerAI, currentPlayer); + beginNewGame(firstPlayerAI, secondPlayerAI, currentPlayer); - field.settingPhase = settingPhase; + field.settingPhase = settingPhase; - return true; + return true; } //----------------------------------------------------------------------------- @@ -103,40 +100,37 @@ bool Position::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, //----------------------------------------------------------------------------- void Position::setUpCalcPossibleMoves(Player *player) { - // locals - unsigned int i, j, k, movingDirection; + // locals + unsigned int i, j, k, movingDirection; - for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) - { - for (j = 0; j < fieldStruct::size; j++) - { + for (player->numPossibleMoves = 0, i = 0; i < fieldStruct::size; i++) { + for (j = 0; j < fieldStruct::size; j++) { - // is stone from player ? - if (field.board[i] != player->id) - continue; + // is stone from player ? + if (field.board[i] != player->id) + continue; - // is destination free ? - if (field.board[j] != field.squareIsFree) - continue; + // is destination free ? + if (field.board[j] != field.squareIsFree) + continue; - // when current player has only 3 stones he is allowed to spring his stone - if (player->numStones > 3 || field.settingPhase) - { + // when current player has only 3 stones he is allowed to spring his stone + if (player->numStones > 3 || field.settingPhase) { - // determine moving direction - for (k = 0, movingDirection = 4; k < 4; k++) - if (field.connectedSquare[i][k] == j) - movingDirection = k; + // determine moving direction + for (k = 0, movingDirection = 4; k < 4; k++) + if (field.connectedSquare[i][k] == j) + movingDirection = k; - // are both squares connected ? - if (movingDirection == 4) - continue; - } + // are both squares connected ? + if (movingDirection == 4) + continue; + } - // everything is ok - player->numPossibleMoves++; - } - } + // everything is ok + player->numPossibleMoves++; + } + } } //----------------------------------------------------------------------------- @@ -145,17 +139,16 @@ void Position::setUpCalcPossibleMoves(Player *player) //----------------------------------------------------------------------------- void Position::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour) { - // locals - int rowOwner = field.board[stone]; + // locals + int rowOwner = field.board[stone]; - // mill closed ? - if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) - { + // mill closed ? + if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) { - field.stonePartOfMill[stone]++; - field.stonePartOfMill[firstNeighbour]++; - field.stonePartOfMill[secondNeighbour]++; - } + field.stonePartOfMill[stone]++; + field.stonePartOfMill[firstNeighbour]++; + field.stonePartOfMill[secondNeighbour]++; + } } //----------------------------------------------------------------------------- @@ -164,85 +157,80 @@ void Position::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeig //----------------------------------------------------------------------------- bool Position::put_piece(unsigned int pos, int player) { - // locals - unsigned int i; - unsigned int numberOfMillsCurrentPlayer = 0, numberOfMillsOpponentPlayer = 0; - Player *myPlayer = (player == field.curPlayer->id) ? field.curPlayer : field.oppPlayer; + // locals + unsigned int i; + unsigned int numberOfMillsCurrentPlayer = 0, numberOfMillsOpponentPlayer = 0; + Player *myPlayer = (player == field.curPlayer->id) ? field.curPlayer : field.oppPlayer; - // check parameters - if (player != fieldStruct::playerOne && player != fieldStruct::playerTwo) - return false; - if (pos >= fieldStruct::size) - return false; - if (field.board[pos] != field.squareIsFree) - return false; + // check parameters + if (player != fieldStruct::playerOne && player != fieldStruct::playerTwo) + return false; + if (pos >= fieldStruct::size) + return false; + if (field.board[pos] != field.squareIsFree) + return false; - // set stone - field.board[pos] = player; - myPlayer->numStones++; - field.stonesSet++; + // set stone + field.board[pos] = player; + myPlayer->numStones++; + field.stonesSet++; - // setting phase finished ? - if (field.stonesSet == 18) - field.settingPhase = false; + // setting phase finished ? + if (field.stonesSet == 18) + field.settingPhase = false; - // calc possible moves - setUpCalcPossibleMoves(field.curPlayer); - setUpCalcPossibleMoves(field.oppPlayer); + // calc possible moves + setUpCalcPossibleMoves(field.curPlayer); + setUpCalcPossibleMoves(field.oppPlayer); - // zero - for (i = 0; i < fieldStruct::size; i++) - field.stonePartOfMill[i] = 0; + // zero + for (i = 0; i < fieldStruct::size; i++) + field.stonePartOfMill[i] = 0; - // go in every direction - for (i = 0; i < fieldStruct::size; i++) - { - setUpSetWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1]); - setUpSetWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1]); - } + // go in every direction + for (i = 0; i < fieldStruct::size; i++) { + setUpSetWarningAndMill(i, field.neighbour[i][0][0], field.neighbour[i][0][1]); + setUpSetWarningAndMill(i, field.neighbour[i][1][0], field.neighbour[i][1][1]); + } - // since every mill was detected 3 times - for (i = 0; i < fieldStruct::size; i++) - field.stonePartOfMill[i] /= 3; + // since every mill was detected 3 times + for (i = 0; i < fieldStruct::size; i++) + field.stonePartOfMill[i] /= 3; - // count completed mills - for (i = 0; i < fieldStruct::size; i++) - { - if (field.board[i] == field.curPlayer->id) - numberOfMillsCurrentPlayer += field.stonePartOfMill[i]; - else - numberOfMillsOpponentPlayer += field.stonePartOfMill[i]; - } - numberOfMillsCurrentPlayer /= 3; - numberOfMillsOpponentPlayer /= 3; + // count completed mills + for (i = 0; i < fieldStruct::size; i++) { + if (field.board[i] == field.curPlayer->id) + numberOfMillsCurrentPlayer += field.stonePartOfMill[i]; + else + numberOfMillsOpponentPlayer += field.stonePartOfMill[i]; + } + numberOfMillsCurrentPlayer /= 3; + numberOfMillsOpponentPlayer /= 3; - // stonesSet & numStonesMissing - if (field.settingPhase) - { - // ... This calculation is not correct! It is possible that some mills did not cause a stone removal. - field.curPlayer->numStonesMissing = numberOfMillsOpponentPlayer; - field.oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - field.stoneMustBeRemoved; - field.stonesSet = field.curPlayer->numStones + field.oppPlayer->numStones + field.curPlayer->numStonesMissing + field.oppPlayer->numStonesMissing; - } - else - { - field.stonesSet = 18; - field.curPlayer->numStonesMissing = 9 - field.curPlayer->numStones; - field.oppPlayer->numStonesMissing = 9 - field.oppPlayer->numStones; - } + // stonesSet & numStonesMissing + if (field.settingPhase) { + // ... This calculation is not correct! It is possible that some mills did not cause a stone removal. + field.curPlayer->numStonesMissing = numberOfMillsOpponentPlayer; + field.oppPlayer->numStonesMissing = numberOfMillsCurrentPlayer - field.stoneMustBeRemoved; + field.stonesSet = field.curPlayer->numStones + field.oppPlayer->numStones + field.curPlayer->numStonesMissing + field.oppPlayer->numStonesMissing; + } else { + field.stonesSet = 18; + field.curPlayer->numStonesMissing = 9 - field.curPlayer->numStones; + field.oppPlayer->numStonesMissing = 9 - field.oppPlayer->numStones; + } - // when opponent is unable to move than current player has won - if ((!field.curPlayer->numPossibleMoves) && (!field.settingPhase) && (!field.stoneMustBeRemoved) && (field.curPlayer->numStones > 3)) - winner = field.oppPlayer->id; - else if ((field.curPlayer->numStones < 3) && (!field.settingPhase)) - winner = field.oppPlayer->id; - else if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) - winner = field.curPlayer->id; - else - winner = 0; + // when opponent is unable to move than current player has won + if ((!field.curPlayer->numPossibleMoves) && (!field.settingPhase) && (!field.stoneMustBeRemoved) && (field.curPlayer->numStones > 3)) + winner = field.oppPlayer->id; + else if ((field.curPlayer->numStones < 3) && (!field.settingPhase)) + winner = field.oppPlayer->id; + else if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) + winner = field.curPlayer->id; + else + winner = 0; - // everything is ok - return true; + // everything is ok + return true; } //----------------------------------------------------------------------------- @@ -251,10 +239,10 @@ bool Position::put_piece(unsigned int pos, int player) //----------------------------------------------------------------------------- bool Position::settingPhaseHasFinished() { - // remember initialField - field.copyBoard(&initialField); + // remember initialField + field.copyBoard(&initialField); - return true; + return true; } //----------------------------------------------------------------------------- @@ -263,21 +251,20 @@ bool Position::settingPhaseHasFinished() //----------------------------------------------------------------------------- bool Position::getField(int *pField) { - unsigned int index; + unsigned int index; - // if no log is available than no game is in progress and board is invalid - if (moveLogFrom == nullptr) - return false; + // if no log is available than no game is in progress and board is invalid + if (moveLogFrom == nullptr) + return false; - for (index = 0; index < field.size; index++) - { - if (field.warnings[index] != field.noWarning) - pField[index] = (int)field.warnings[index]; - else - pField[index] = field.board[index]; - } + for (index = 0; index < field.size; index++) { + if (field.warnings[index] != field.noWarning) + pField[index] = (int)field.warnings[index]; + else + pField[index] = field.board[index]; + } - return true; + return true; } //----------------------------------------------------------------------------- @@ -286,15 +273,14 @@ bool Position::getField(int *pField) //----------------------------------------------------------------------------- void Position::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned int *to) { - unsigned int index; + unsigned int index; - numMovesDone = movesDone; + numMovesDone = movesDone; - for (index = 0; index < movesDone; index++) - { - from[index] = moveLogFrom[index]; - to[index] = moveLogTo[index]; - } + for (index = 0; index < movesDone; index++) { + from[index] = moveLogFrom[index]; + to[index] = moveLogTo[index]; + } } //----------------------------------------------------------------------------- @@ -303,11 +289,11 @@ void Position::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned i //----------------------------------------------------------------------------- void Position::setNextPlayer() { - Player *tmpPlayer; + Player *tmpPlayer; - tmpPlayer = field.curPlayer; - field.curPlayer = field.oppPlayer; - field.oppPlayer = tmpPlayer; + tmpPlayer = field.curPlayer; + field.curPlayer = field.oppPlayer; + field.oppPlayer = tmpPlayer; } //----------------------------------------------------------------------------- @@ -316,10 +302,10 @@ void Position::setNextPlayer() //----------------------------------------------------------------------------- bool Position::isCurrentPlayerHuman() { - if (field.curPlayer->id == field.playerOne) - return (playerOneAI == nullptr) ? true : false; - else - return (playerTwoAI == nullptr) ? true : false; + if (field.curPlayer->id == field.playerOne) + return (playerOneAI == nullptr) ? true : false; + else + return (playerTwoAI == nullptr) ? true : false; } //----------------------------------------------------------------------------- @@ -328,10 +314,10 @@ bool Position::isCurrentPlayerHuman() //----------------------------------------------------------------------------- bool Position::isOpponentPlayerHuman() { - if (field.oppPlayer->id == field.playerOne) - return (playerOneAI == nullptr) ? true : false; - else - return (playerTwoAI == nullptr) ? true : false; + if (field.oppPlayer->id == field.playerOne) + return (playerOneAI == nullptr) ? true : false; + else + return (playerTwoAI == nullptr) ? true : false; } //----------------------------------------------------------------------------- @@ -340,14 +326,12 @@ bool Position::isOpponentPlayerHuman() //----------------------------------------------------------------------------- void Position::setAI(int player, MillAI *AI) { - if (player == field.playerOne) - { - playerOneAI = AI; - } - if (player == field.playerTwo) - { - playerTwoAI = AI; - } + if (player == field.playerOne) { + playerOneAI = AI; + } + if (player == field.playerTwo) { + playerTwoAI = AI; + } } //----------------------------------------------------------------------------- @@ -356,14 +340,14 @@ void Position::setAI(int player, MillAI *AI) //----------------------------------------------------------------------------- void Position::getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo) { - fieldStruct theField; - *pushFrom = field.size; - *pushTo = field.size; - theField.createBoard(); - field.copyBoard(&theField); - if (AI != nullptr && (field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) - AI->play(&theField, pushFrom, pushTo); - theField.deleteBoard(); + fieldStruct theField; + *pushFrom = field.size; + *pushTo = field.size; + theField.createBoard(); + field.copyBoard(&theField); + if (AI != nullptr && (field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) + AI->play(&theField, pushFrom, pushTo); + theField.deleteBoard(); } //----------------------------------------------------------------------------- @@ -372,27 +356,23 @@ void Position::getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned //----------------------------------------------------------------------------- void Position::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo) { - fieldStruct theField; - *pushFrom = field.size; - *pushTo = field.size; - theField.createBoard(); - field.copyBoard(&theField); + fieldStruct theField; + *pushFrom = field.size; + *pushTo = field.size; + theField.createBoard(); + field.copyBoard(&theField); - if ((field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) - { - if (field.curPlayer->id == field.playerOne) - { - if (playerOneAI != nullptr) - playerOneAI->play(&theField, pushFrom, pushTo); - } - else - { - if (playerTwoAI != nullptr) - playerTwoAI->play(&theField, pushFrom, pushTo); - } - } + if ((field.settingPhase || field.curPlayer->numPossibleMoves > 0) && winner == 0) { + if (field.curPlayer->id == field.playerOne) { + if (playerOneAI != nullptr) + playerOneAI->play(&theField, pushFrom, pushTo); + } else { + if (playerTwoAI != nullptr) + playerTwoAI->play(&theField, pushFrom, pushTo); + } + } - theField.deleteBoard(); + theField.deleteBoard(); } //----------------------------------------------------------------------------- @@ -401,39 +381,38 @@ void Position::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo) //----------------------------------------------------------------------------- bool Position::isNormalMovePossible(unsigned int from, unsigned int to, Player *player) { - // locals - unsigned int movingDirection, i; + // locals + unsigned int movingDirection, i; - // parameter ok ? - if (from >= field.size) - return false; - if (to >= field.size) - return false; + // parameter ok ? + if (from >= field.size) + return false; + if (to >= field.size) + return false; - // is stone from player ? - if (field.board[from] != player->id) - return false; + // is stone from player ? + if (field.board[from] != player->id) + return false; - // is destination free ? - if (field.board[to] != field.squareIsFree) - return false; + // is destination free ? + if (field.board[to] != field.squareIsFree) + return false; - // when current player has only 3 stones he is allowed to spring his stone - if (player->numStones > 3 || field.settingPhase) - { + // when current player has only 3 stones he is allowed to spring his stone + if (player->numStones > 3 || field.settingPhase) { - // determine moving direction - for (i = 0, movingDirection = 4; i < 4; i++) - if (field.connectedSquare[from][i] == to) - movingDirection = i; + // determine moving direction + for (i = 0, movingDirection = 4; i < 4; i++) + if (field.connectedSquare[from][i] == to) + movingDirection = i; - // are both squares connected ? - if (movingDirection == 4) - return false; - } + // are both squares connected ? + if (movingDirection == 4) + return false; + } - // everything is ok - return true; + // everything is ok + return true; } //----------------------------------------------------------------------------- @@ -442,40 +421,35 @@ bool Position::isNormalMovePossible(unsigned int from, unsigned int to, Player * //----------------------------------------------------------------------------- void Position::calcPossibleMoves(Player *player) { - // locals - unsigned int i, j; + // locals + unsigned int i, j; - // zero - for (i = 0; i < MAX_NUM_POS_MOVES; i++) - player->posTo[i] = field.size; - for (i = 0; i < MAX_NUM_POS_MOVES; i++) - player->posFrom[i] = field.size; + // zero + for (i = 0; i < MAX_NUM_POS_MOVES; i++) + player->posTo[i] = field.size; + for (i = 0; i < MAX_NUM_POS_MOVES; i++) + player->posFrom[i] = field.size; - // calc - for (player->numPossibleMoves = 0, i = 0; i < field.size; i++) - { - for (j = 0; j < field.size; j++) - { - if (isNormalMovePossible(i, j, player)) - { - player->posFrom[player->numPossibleMoves] = i; - player->posTo[player->numPossibleMoves] = j; - player->numPossibleMoves++; - } - } - } + // calc + for (player->numPossibleMoves = 0, i = 0; i < field.size; i++) { + for (j = 0; j < field.size; j++) { + if (isNormalMovePossible(i, j, player)) { + player->posFrom[player->numPossibleMoves] = i; + player->posTo[player->numPossibleMoves] = j; + player->numPossibleMoves++; + } + } + } - // stoneMoveAble - for (i = 0; i < field.size; i++) - { - for (j = 0; j < 4; j++) - { - if (field.board[i] == player->id) - field.stoneMoveAble[i][j] = isNormalMovePossible(i, field.connectedSquare[i][j], player); - else - field.stoneMoveAble[i][j] = false; - } - } + // stoneMoveAble + for (i = 0; i < field.size; i++) { + for (j = 0; j < 4; j++) { + if (field.board[i] == player->id) + field.stoneMoveAble[i][j] = isNormalMovePossible(i, field.connectedSquare[i][j], player); + else + field.stoneMoveAble[i][j] = false; + } + } } //----------------------------------------------------------------------------- @@ -484,26 +458,25 @@ void Position::calcPossibleMoves(Player *player) //----------------------------------------------------------------------------- void Position::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour, bool isNewStone) { - // locals - int rowOwner = field.board[stone]; - unsigned int rowOwnerWarning = (rowOwner == field.playerOne) ? field.playerOneWarning : field.playerTwoWarning; + // locals + int rowOwner = field.board[stone]; + unsigned int rowOwnerWarning = (rowOwner == field.playerOne) ? field.playerOneWarning : field.playerTwoWarning; - // mill closed ? - if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) - { + // mill closed ? + if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) { - field.stonePartOfMill[stone]++; - field.stonePartOfMill[firstNeighbour]++; - field.stonePartOfMill[secondNeighbour]++; - if (isNewStone) - field.stoneMustBeRemoved = 1; - } + field.stonePartOfMill[stone]++; + field.stonePartOfMill[firstNeighbour]++; + field.stonePartOfMill[secondNeighbour]++; + if (isNewStone) + field.stoneMustBeRemoved = 1; + } - //warning ? - if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == field.squareIsFree && field.board[secondNeighbour] == rowOwner) - field.warnings[firstNeighbour] |= rowOwnerWarning; - if (rowOwner != field.squareIsFree && field.board[secondNeighbour] == field.squareIsFree && field.board[firstNeighbour] == rowOwner) - field.warnings[secondNeighbour] |= rowOwnerWarning; + //warning ? + if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == field.squareIsFree && field.board[secondNeighbour] == rowOwner) + field.warnings[firstNeighbour] |= rowOwnerWarning; + if (rowOwner != field.squareIsFree && field.board[secondNeighbour] == field.squareIsFree && field.board[firstNeighbour] == rowOwner) + field.warnings[secondNeighbour] |= rowOwnerWarning; } //----------------------------------------------------------------------------- @@ -512,35 +485,34 @@ void Position::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour //----------------------------------------------------------------------------- void Position::updateMillsAndWarnings(unsigned int newStone) { - // locals - unsigned int i; - bool atLeastOneStoneRemoveAble; + // locals + unsigned int i; + bool atLeastOneStoneRemoveAble; - // zero - for (i = 0; i < field.size; i++) - field.stonePartOfMill[i] = 0; - for (i = 0; i < field.size; i++) - field.warnings[i] = field.noWarning; - field.stoneMustBeRemoved = 0; + // zero + for (i = 0; i < field.size; i++) + field.stonePartOfMill[i] = 0; + for (i = 0; i < field.size; i++) + field.warnings[i] = field.noWarning; + field.stoneMustBeRemoved = 0; - // go in every direction - for (i = 0; i < field.size; i++) - { + // go in every direction + 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][1][0], field.neighbour[i][1][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); + } - // since every mill was detected 3 times - for (i = 0; i < field.size; i++) - field.stonePartOfMill[i] /= 3; + // since every mill was detected 3 times + for (i = 0; i < field.size; i++) + field.stonePartOfMill[i] /= 3; - // no stone must be removed if each belongs to a mill - for (atLeastOneStoneRemoveAble = false, i = 0; i < field.size; i++) - if (field.stonePartOfMill[i] == 0 && field.board[i] == field.oppPlayer->id) - atLeastOneStoneRemoveAble = true; - if (!atLeastOneStoneRemoveAble) - field.stoneMustBeRemoved = 0; + // no stone must be removed if each belongs to a mill + for (atLeastOneStoneRemoveAble = false, i = 0; i < field.size; i++) + if (field.stonePartOfMill[i] == 0 && field.board[i] == field.oppPlayer->id) + atLeastOneStoneRemoveAble = true; + if (!atLeastOneStoneRemoveAble) + field.stoneMustBeRemoved = 0; } //----------------------------------------------------------------------------- @@ -549,138 +521,133 @@ void Position::updateMillsAndWarnings(unsigned int newStone) //----------------------------------------------------------------------------- bool Position::do_move(unsigned int pushFrom, unsigned int pushTo) { - // avoid index override - if (movesDone >= MAX_NUM_MOVES) - return false; + // avoid index override + if (movesDone >= MAX_NUM_MOVES) + return false; - // is game still running ? - if (winner) - return false; + // is game still running ? + if (winner) + return false; - // handle the remove of a stone - if (field.stoneMustBeRemoved) - { + // handle the remove of a stone + if (field.stoneMustBeRemoved) { - // parameter ok ? - if (pushFrom >= field.size) - return false; + // parameter ok ? + if (pushFrom >= field.size) + return false; - // is it stone from the opponent ? - if (field.board[pushFrom] != field.oppPlayer->id) - return false; + // is it stone from the opponent ? + if (field.board[pushFrom] != field.oppPlayer->id) + return false; - // is stone not part of mill? - if (field.stonePartOfMill[pushFrom]) - return false; + // is stone not part of mill? + if (field.stonePartOfMill[pushFrom]) + return false; - // remove stone - moveLogFrom[movesDone] = pushFrom; - moveLogTo[movesDone] = field.size; - field.board[pushFrom] = field.squareIsFree; - field.oppPlayer->numStonesMissing++; - field.oppPlayer->numStones--; - field.stoneMustBeRemoved--; - movesDone++; + // remove stone + moveLogFrom[movesDone] = pushFrom; + moveLogTo[movesDone] = field.size; + field.board[pushFrom] = field.squareIsFree; + field.oppPlayer->numStonesMissing++; + field.oppPlayer->numStones--; + field.stoneMustBeRemoved--; + movesDone++; - // is the game finished ? - if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) - winner = field.curPlayer->id; + // is the game finished ? + if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) + winner = field.curPlayer->id; - // update warnings & mills - updateMillsAndWarnings(field.size); + // update warnings & mills + updateMillsAndWarnings(field.size); - // calc possibilities - calcPossibleMoves(field.curPlayer); - calcPossibleMoves(field.oppPlayer); + // calc possibilities + calcPossibleMoves(field.curPlayer); + calcPossibleMoves(field.oppPlayer); - // is opponent unable to move ? - if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) - winner = field.curPlayer->id; + // is opponent unable to move ? + if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) + winner = field.curPlayer->id; - // next player - if (!field.stoneMustBeRemoved) - setNextPlayer(); + // next player + if (!field.stoneMustBeRemoved) + setNextPlayer(); - // everything is ok - return true; + // everything is ok + return true; - // handle setting phase - } - else if (field.settingPhase) - { + // handle setting phase + } else if (field.settingPhase) { - // parameter ok ? - if (pushTo >= field.size) - return false; + // parameter ok ? + if (pushTo >= field.size) + return false; - // is destination free ? - if (field.board[pushTo] != field.squareIsFree) - return false; + // is destination free ? + if (field.board[pushTo] != field.squareIsFree) + return false; - // set stone - moveLogFrom[movesDone] = field.size; - moveLogTo[movesDone] = pushTo; - field.board[pushTo] = field.curPlayer->id; - field.curPlayer->numStones++; - field.stonesSet++; - movesDone++; + // set stone + moveLogFrom[movesDone] = field.size; + moveLogTo[movesDone] = pushTo; + field.board[pushTo] = field.curPlayer->id; + field.curPlayer->numStones++; + field.stonesSet++; + movesDone++; - // update warnings & mills - updateMillsAndWarnings(pushTo); + // update warnings & mills + updateMillsAndWarnings(pushTo); - // calc possibilities - calcPossibleMoves(field.curPlayer); - calcPossibleMoves(field.oppPlayer); + // calc possibilities + calcPossibleMoves(field.curPlayer); + calcPossibleMoves(field.oppPlayer); - // setting phase finished ? - if (field.stonesSet == 18) - field.settingPhase = false; + // setting phase finished ? + if (field.stonesSet == 18) + field.settingPhase = false; - // is opponent unable to move ? - if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) - winner = field.curPlayer->id; + // is opponent unable to move ? + if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) + winner = field.curPlayer->id; - // next player - if (!field.stoneMustBeRemoved) - setNextPlayer(); + // next player + if (!field.stoneMustBeRemoved) + setNextPlayer(); - // everything is ok - return true; + // everything is ok + return true; - // normal move - } - else - { + // normal move + } else { - // is move possible ? - if (!isNormalMovePossible(pushFrom, pushTo, field.curPlayer)) - return false; + // is move possible ? + if (!isNormalMovePossible(pushFrom, pushTo, field.curPlayer)) + return false; - // move stone - moveLogFrom[movesDone] = pushFrom; - moveLogTo[movesDone] = pushTo; - field.board[pushFrom] = field.squareIsFree; - field.board[pushTo] = field.curPlayer->id; - movesDone++; + // move stone + moveLogFrom[movesDone] = pushFrom; + moveLogTo[movesDone] = pushTo; + field.board[pushFrom] = field.squareIsFree; + field.board[pushTo] = field.curPlayer->id; + movesDone++; - // update warnings & mills - updateMillsAndWarnings(pushTo); + // update warnings & mills + updateMillsAndWarnings(pushTo); - // calc possibilities - calcPossibleMoves(field.curPlayer); - calcPossibleMoves(field.oppPlayer); + // calc possibilities + calcPossibleMoves(field.curPlayer); + calcPossibleMoves(field.oppPlayer); - // is opponent unable to move ? - if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) - winner = field.curPlayer->id; + // is opponent unable to move ? + if (field.oppPlayer->numPossibleMoves == 0 && !field.settingPhase) + winner = field.curPlayer->id; - // next player - if (!field.stoneMustBeRemoved) - setNextPlayer(); + // next player + if (!field.stoneMustBeRemoved) + setNextPlayer(); - // everything is ok - return true; - } + // everything is ok + return true; + } } //----------------------------------------------------------------------------- @@ -689,19 +656,19 @@ bool Position::do_move(unsigned int pushFrom, unsigned int pushTo) //----------------------------------------------------------------------------- bool Position::setCurrentGameState(fieldStruct *curState) { - curState->copyBoard(&field); + curState->copyBoard(&field); - winner = 0; - movesDone = 0; + winner = 0; + movesDone = 0; - if ((field.curPlayer->numStones < 3) && (!field.settingPhase)) - winner = field.oppPlayer->id; - if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) - winner = field.curPlayer->id; - if ((field.curPlayer->numPossibleMoves == 0) && (!field.settingPhase)) - winner = field.oppPlayer->id; + if ((field.curPlayer->numStones < 3) && (!field.settingPhase)) + winner = field.oppPlayer->id; + if ((field.oppPlayer->numStones < 3) && (!field.settingPhase)) + winner = field.curPlayer->id; + if ((field.curPlayer->numPossibleMoves == 0) && (!field.settingPhase)) + winner = field.oppPlayer->id; - return true; + return true; } //----------------------------------------------------------------------------- @@ -710,73 +677,61 @@ bool Position::setCurrentGameState(fieldStruct *curState) //----------------------------------------------------------------------------- bool Position::compareWithField(fieldStruct *compareField) { - unsigned int i, j; - bool ret = true; + unsigned int i, j; + bool ret = true; - if (!comparePlayers(field.curPlayer, compareField->curPlayer)) - { - cout << "error - curPlayer differs!" << endl; - ret = false; - } - if (!comparePlayers(field.oppPlayer, compareField->oppPlayer)) - { - cout << "error - oppPlayer differs!" << endl; - ret = false; - } + if (!comparePlayers(field.curPlayer, compareField->curPlayer)) { + cout << "error - curPlayer differs!" << endl; + ret = false; + } + if (!comparePlayers(field.oppPlayer, compareField->oppPlayer)) { + cout << "error - oppPlayer differs!" << endl; + ret = false; + } - if (field.stonesSet != compareField->stonesSet) - { - cout << "error - stonesSet differs!" << endl; - ret = false; - } - if (field.settingPhase != compareField->settingPhase) - { - cout << "error - settingPhase differs!" << endl; - ret = false; - } - if (field.stoneMustBeRemoved != compareField->stoneMustBeRemoved) - { - cout << "error - stoneMustBeRemoved differs!" << endl; - ret = false; - } + if (field.stonesSet != compareField->stonesSet) { + cout << "error - stonesSet differs!" << endl; + ret = false; + } + if (field.settingPhase != compareField->settingPhase) { + cout << "error - settingPhase differs!" << endl; + ret = false; + } + if (field.stoneMustBeRemoved != compareField->stoneMustBeRemoved) { + cout << "error - stoneMustBeRemoved differs!" << endl; + ret = false; + } - for (i = 0; i < field.size; i++) - { + for (i = 0; i < field.size; i++) { - if (field.board[i] != compareField->board[i]) - { - cout << "error - board[] differs!" << endl; - ret = false; - } - if (field.warnings[i] != compareField->warnings[i]) - { - cout << "error - warnings[] differs!" << endl; - ret = false; - } - if (field.stonePartOfMill[i] != compareField->stonePartOfMill[i]) - { - cout << "error - stonePart[] differs!" << endl; - ret = false; - } + if (field.board[i] != compareField->board[i]) { + cout << "error - board[] differs!" << endl; + ret = false; + } + if (field.warnings[i] != compareField->warnings[i]) { + cout << "error - warnings[] differs!" << endl; + ret = false; + } + if (field.stonePartOfMill[i] != compareField->stonePartOfMill[i]) { + cout << "error - stonePart[] differs!" << endl; + ret = false; + } - for (j = 0; j < 4; j++) - { + for (j = 0; j < 4; j++) { - if (field.connectedSquare[i][j] != compareField->connectedSquare[i][j]) - { - cout << "error - connectedSquare[] 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]) - { - cout << "error - neighbour differs!" << endl; - ret = false; - } - } - } + if (field.connectedSquare[i][j] != compareField->connectedSquare[i][j]) { + cout << "error - connectedSquare[] 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]) { + cout << "error - neighbour differs!" << endl; + ret = false; + } + } + } - return ret; + return ret; } //----------------------------------------------------------------------------- @@ -785,39 +740,34 @@ bool Position::compareWithField(fieldStruct *compareField) //----------------------------------------------------------------------------- bool Position::comparePlayers(Player *playerA, Player *playerB) { - // unsigned int i; - bool ret = true; + // unsigned int i; + bool ret = true; - if (playerA->numStonesMissing != playerB->numStonesMissing) - { - cout << "error - numStonesMissing differs!" << endl; - ret = false; - } - if (playerA->numStones != playerB->numStones) - { - cout << "error - numStones differs!" << endl; - ret = false; - } - if (playerA->id != playerB->id) - { - cout << "error - id differs!" << endl; - ret = false; - } - if (playerA->warning != playerB->warning) - { - cout << "error - warning differs!" << endl; - ret = false; - } - if (playerA->numPossibleMoves != playerB->numPossibleMoves) - { - cout << "error - numPossibleMoves differs!" << endl; - ret = false; - } + if (playerA->numStonesMissing != playerB->numStonesMissing) { + cout << "error - numStonesMissing differs!" << endl; + ret = false; + } + if (playerA->numStones != playerB->numStones) { + cout << "error - numStones differs!" << endl; + ret = false; + } + if (playerA->id != playerB->id) { + cout << "error - id differs!" << endl; + ret = false; + } + if (playerA->warning != playerB->warning) { + cout << "error - warning differs!" << endl; + ret = false; + } + if (playerA->numPossibleMoves != playerB->numPossibleMoves) { + cout << "error - numPossibleMoves differs!" << endl; + ret = false; + } - // for (i=0; iposFrom[i] = playerB->posFrom[i]) return false; - // for (i=0; iposTo [i] = playerB->posTo [i]) return false; + // for (i=0; iposFrom[i] = playerB->posFrom[i]) return false; + // for (i=0; iposTo [i] = playerB->posTo [i]) return false; - return ret; + return ret; } //----------------------------------------------------------------------------- @@ -827,7 +777,7 @@ bool Position::comparePlayers(Player *playerA, Player *playerB) //----------------------------------------------------------------------------- void Position::printBoard() { - field.printBoard(); + field.printBoard(); } //----------------------------------------------------------------------------- @@ -836,38 +786,35 @@ void Position::printBoard() //----------------------------------------------------------------------------- void Position::undo_move(void) { - // locals - unsigned int *moveLogFrom_bak = new unsigned int[movesDone]; - unsigned int *moveLogTo_bak = new unsigned int[movesDone]; - unsigned int movesDone_bak = movesDone; - unsigned int i; + // locals + unsigned int *moveLogFrom_bak = new unsigned int[movesDone]; + unsigned int *moveLogTo_bak = new unsigned int[movesDone]; + unsigned int movesDone_bak = movesDone; + unsigned int i; - // at least one move must be done - if (movesDone) - { + // at least one move must be done + if (movesDone) { - // make backup of log - for (i = 0; i < movesDone; i++) - { - moveLogFrom_bak[i] = moveLogFrom[i]; - moveLogTo_bak[i] = moveLogTo[i]; - } + // make backup of log + for (i = 0; i < movesDone; i++) { + moveLogFrom_bak[i] = moveLogFrom[i]; + moveLogTo_bak[i] = moveLogTo[i]; + } - // reset - initialField.copyBoard(&field); - winner = 0; - movesDone = 0; + // reset + initialField.copyBoard(&field); + winner = 0; + movesDone = 0; - // and play again - for (i = 0; i < movesDone_bak - 1; i++) - { - do_move(moveLogFrom_bak[i], moveLogTo_bak[i]); - } - } + // and play again + for (i = 0; i < movesDone_bak - 1; i++) { + do_move(moveLogFrom_bak[i], moveLogTo_bak[i]); + } + } - // free mem - delete[] moveLogFrom_bak; - delete[] moveLogTo_bak; + // free mem + delete[] moveLogFrom_bak; + delete[] moveLogTo_bak; } //----------------------------------------------------------------------------- @@ -876,14 +823,11 @@ void Position::undo_move(void) //----------------------------------------------------------------------------- void Position::calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting) { - if (getCurrentPlayer() == fieldStruct::playerTwo) - { - numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; - numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; - } - else - { - numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; - numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; - } + if (getCurrentPlayer() == fieldStruct::playerTwo) { + numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; + numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; + } else { + numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones; + numBlackStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones; + } } \ No newline at end of file diff --git a/src/perfect/position.h b/src/perfect/position.h index 50824670..3e52f96c 100644 --- a/src/perfect/position.h +++ b/src/perfect/position.h @@ -1,9 +1,9 @@ /*********************************************************************\ - Position.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + Position.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef MUEHLE_H @@ -45,95 +45,95 @@ using namespace std; class Position { private: - // Variables - unsigned int *moveLogFrom, *moveLogTo, movesDone; // array containing the history of moves done - MillAI *playerOneAI; // class-pointer to the AI of player one - MillAI *playerTwoAI; // class-pointer to the AI of player two - fieldStruct field; // current board - fieldStruct initialField; // undo of the last move is done by setting the initial board und performing all moves saved in history - int winner; // playerId of the player who has won the game. zero if game is still running. - int beginningPlayer; // playerId of the player who makes the first move + // Variables + unsigned int *moveLogFrom, *moveLogTo, movesDone; // array containing the history of moves done + MillAI *playerOneAI; // class-pointer to the AI of player one + MillAI *playerTwoAI; // class-pointer to the AI of player two + fieldStruct field; // current board + fieldStruct initialField; // undo of the last move is done by setting the initial board und performing all moves saved in history + int winner; // playerId of the player who has won the game. zero if game is still running. + int beginningPlayer; // playerId of the player who makes the first move - // Functions - void exit(); - void setNextPlayer(); - void calcPossibleMoves(Player *player); - void updateMillsAndWarnings(unsigned int newStone); - bool isNormalMovePossible(unsigned int from, unsigned int to, Player *player); - void setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour, bool isNewStone); + // Functions + void exit(); + void setNextPlayer(); + void calcPossibleMoves(Player *player); + void updateMillsAndWarnings(unsigned int newStone); + bool isNormalMovePossible(unsigned int from, unsigned int to, Player *player); + void setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour, bool isNewStone); public: - // Constructor / destructor - Position(); - ~Position(); + // Constructor / destructor + Position(); + ~Position(); - // Functions - void undo_move(); - void beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer); - void setAI(int player, MillAI *AI); - bool do_move(unsigned int pushFrom, unsigned int pushTo); - void getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo); - bool setCurrentGameState(fieldStruct *curState); - bool compareWithField(fieldStruct *compareField); - bool comparePlayers(Player *playerA, Player *playerB); - void printBoard(); - bool startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer, bool settingPhase); - bool put_piece(unsigned int pos, int player); - bool settingPhaseHasFinished(); - void getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo); - void setUpCalcPossibleMoves(Player *player); - void setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour); - void calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting); + // Functions + void undo_move(); + void beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer); + void setAI(int player, MillAI *AI); + bool do_move(unsigned int pushFrom, unsigned int pushTo); + void getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo); + bool setCurrentGameState(fieldStruct *curState); + bool compareWithField(fieldStruct *compareField); + bool comparePlayers(Player *playerA, Player *playerB); + void printBoard(); + bool startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer, bool settingPhase); + bool put_piece(unsigned int pos, int player); + bool settingPhaseHasFinished(); + void getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo); + void setUpCalcPossibleMoves(Player *player); + void setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour); + void calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting); - // getter - void getLog(unsigned int &numMovesDone, unsigned int *from, unsigned int *to); - bool getField(int *pField); - bool isCurrentPlayerHuman(); - bool isOpponentPlayerHuman(); - bool inSettingPhase() - { - return field.settingPhase; - } - unsigned int mustStoneBeRemoved() - { - return field.stoneMustBeRemoved; - } - int getWinner() - { - return winner; - } - int getCurrentPlayer() - { - return field.curPlayer->id; - } - unsigned int getLastMoveFrom() - { - return (movesDone ? moveLogFrom[movesDone - 1] : field.size); - } - unsigned int getLastMoveTo() - { - return (movesDone ? moveLogTo[movesDone - 1] : field.size); - } - unsigned int getMovesDone() - { - return movesDone; - } - unsigned int getNumStonesSet() - { - return field.stonesSet; - } - int getBeginningPlayer() - { - return beginningPlayer; - } - unsigned int getNumStonOfCurPlayer() - { - return field.curPlayer->numStones; - } - unsigned int getNumStonOfOppPlayer() - { - return field.oppPlayer->numStones; - } + // getter + void getLog(unsigned int &numMovesDone, unsigned int *from, unsigned int *to); + bool getField(int *pField); + bool isCurrentPlayerHuman(); + bool isOpponentPlayerHuman(); + bool inSettingPhase() + { + return field.settingPhase; + } + unsigned int mustStoneBeRemoved() + { + return field.stoneMustBeRemoved; + } + int getWinner() + { + return winner; + } + int getCurrentPlayer() + { + return field.curPlayer->id; + } + unsigned int getLastMoveFrom() + { + return (movesDone ? moveLogFrom[movesDone - 1] : field.size); + } + unsigned int getLastMoveTo() + { + return (movesDone ? moveLogTo[movesDone - 1] : field.size); + } + unsigned int getMovesDone() + { + return movesDone; + } + unsigned int getNumStonesSet() + { + return field.stonesSet; + } + int getBeginningPlayer() + { + return beginningPlayer; + } + unsigned int getNumStonOfCurPlayer() + { + return field.curPlayer->numStones; + } + unsigned int getNumStonOfOppPlayer() + { + return field.oppPlayer->numStones; + } }; #endif diff --git a/src/perfect/randomAI.cpp b/src/perfect/randomAI.cpp index be963f55..0b7dcaf0 100644 --- a/src/perfect/randomAI.cpp +++ b/src/perfect/randomAI.cpp @@ -1,9 +1,9 @@ /********************************************************************* - RandomAI.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + RandomAI.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "randomAI.h" @@ -14,8 +14,8 @@ //----------------------------------------------------------------------------- RandomAI::RandomAI() { - // Init - srand((unsigned)time(nullptr)); + // Init + srand((unsigned)time(nullptr)); } //----------------------------------------------------------------------------- @@ -24,7 +24,7 @@ RandomAI::RandomAI() //----------------------------------------------------------------------------- RandomAI::~RandomAI() { - // Locals + // Locals } //----------------------------------------------------------------------------- @@ -33,68 +33,54 @@ RandomAI::~RandomAI() //----------------------------------------------------------------------------- void RandomAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo) { - // locals - unsigned int from, to, direction; - bool allowedToSpring = (theField->curPlayer->numStones == 3) ? true : false; + // locals + unsigned int from, to, direction; + bool allowedToSpring = (theField->curPlayer->numStones == 3) ? true : false; - // must stone be removed ? - if (theField->stoneMustBeRemoved) - { + // must stone be removed ? + if (theField->stoneMustBeRemoved) { - // search a stone from the enemy - do - { - from = rand() % theField->size; - to = theField->size; - } while (theField->board[from] != theField->oppPlayer->id || theField->stonePartOfMill[from]); + // search a stone from the enemy + do { + from = rand() % theField->size; + to = theField->size; + } while (theField->board[from] != theField->oppPlayer->id || theField->stonePartOfMill[from]); - // still in setting phase ? - } - else if (theField->settingPhase) - { + // still in setting phase ? + } else if (theField->settingPhase) { - // search a free square - do - { - from = theField->size; - to = rand() % theField->size; - } while (theField->board[to] != theField->squareIsFree); + // search a free square + do { + from = theField->size; + to = rand() % theField->size; + } while (theField->board[to] != theField->squareIsFree); - // try to push randomly - } - else - { + // try to push randomly + } else { - do - { - // search an own stone - do - { - from = rand() % theField->size; - } while (theField->board[from] != theField->curPlayer->id); + do { + // search an own stone + do { + from = rand() % theField->size; + } while (theField->board[from] != theField->curPlayer->id); - // select a free square - if (allowedToSpring) - { - do - { - to = rand() % theField->size; - } while (theField->board[to] != theField->squareIsFree); + // select a free square + if (allowedToSpring) { + do { + to = rand() % theField->size; + } while (theField->board[to] != theField->squareIsFree); - // select a connected square - } - else - { - do - { - direction = rand() % 4; - to = theField->connectedSquare[from][direction]; - } while (to == theField->size); - } + // select a connected square + } else { + do { + direction = rand() % 4; + to = theField->connectedSquare[from][direction]; + } while (to == theField->size); + } - } while (theField->board[to] != theField->squareIsFree); - } + } while (theField->board[to] != theField->squareIsFree); + } - *pushFrom = from; - *pushTo = to; + *pushFrom = from; + *pushTo = to; } diff --git a/src/perfect/randomAI.h b/src/perfect/randomAI.h index 82e04d20..2e28b831 100644 --- a/src/perfect/randomAI.h +++ b/src/perfect/randomAI.h @@ -1,9 +1,9 @@ /*********************************************************************\ - RandomAI.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + RandomAI.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef RANDOM_AI_H @@ -18,12 +18,12 @@ class RandomAI : public MillAI { public: - // Constructor / destructor - RandomAI(); - ~RandomAI(); + // Constructor / destructor + RandomAI(); + ~RandomAI(); - // Functions - void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); + // Functions + void play(fieldStruct *theField, unsigned int *pushFrom, unsigned int *pushTo); }; #endif diff --git a/src/perfect/strLib.cpp b/src/perfect/strLib.cpp index b5e12a9c..538dd661 100644 --- a/src/perfect/strLib.cpp +++ b/src/perfect/strLib.cpp @@ -1,9 +1,9 @@ /********************************************************************* - strLib.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + strLib.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "strLib.h" @@ -14,12 +14,12 @@ //----------------------------------------------------------------------------- int MyString::hibit(unsigned int n) { - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - n |= (n >> 16); - return n - (n >> 1); + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); } //----------------------------------------------------------------------------- @@ -36,7 +36,7 @@ MyString::MyString() //----------------------------------------------------------------------------- MyString::MyString(const char *cStr) { - assign(cStr); + assign(cStr); } //----------------------------------------------------------------------------- @@ -45,7 +45,7 @@ MyString::MyString(const char *cStr) //----------------------------------------------------------------------------- MyString::MyString(const WCHAR *cStr) { - assign(cStr); + assign(cStr); } //----------------------------------------------------------------------------- @@ -54,20 +54,18 @@ MyString::MyString(const WCHAR *cStr) //----------------------------------------------------------------------------- MyString::~MyString() { - if (strA != nullptr) - { - delete[] strA; - strA = nullptr; - } - if (strW != nullptr) - { - delete[] strW; - strW = nullptr; - } - strW = nullptr; - strA = nullptr; - length = 0; - reserved = 0; + if (strA != nullptr) { + delete[] strA; + strA = nullptr; + } + if (strW != nullptr) { + delete[] strW; + strW = nullptr; + } + strW = nullptr; + strA = nullptr; + length = 0; + reserved = 0; } //----------------------------------------------------------------------------- @@ -76,7 +74,7 @@ MyString::~MyString() //----------------------------------------------------------------------------- const char *MyString::c_strA() { - return strA; + return strA; } //----------------------------------------------------------------------------- @@ -85,7 +83,7 @@ const char *MyString::c_strA() //----------------------------------------------------------------------------- const WCHAR *MyString::c_strW() { - return strW; + return strW; } //----------------------------------------------------------------------------- @@ -94,25 +92,25 @@ const WCHAR *MyString::c_strW() //----------------------------------------------------------------------------- MyString &MyString::assign(const char *cStr) { - // locals - size_t convertedChars = 0; - size_t newLength = strlen(cStr); - size_t newReserved = (size_t)hibit((unsigned int)newLength) * 2; + // locals + size_t convertedChars = 0; + size_t newLength = strlen(cStr); + size_t newReserved = (size_t)hibit((unsigned int)newLength) * 2; - if (reserved < newReserved) - this->~MyString(); - if (strA == nullptr) - strA = new char[newReserved]; - if (strW == nullptr) - strW = new WCHAR[newReserved]; + if (reserved < newReserved) + this->~MyString(); + if (strA == nullptr) + strA = new char[newReserved]; + if (strW == nullptr) + strW = new WCHAR[newReserved]; - reserved = newReserved; - length = newLength; + reserved = newReserved; + length = newLength; - strcpy_s(strA, newReserved, cStr); - mbstowcs_s(&convertedChars, strW, newLength + 1, cStr, _TRUNCATE); + strcpy_s(strA, newReserved, cStr); + mbstowcs_s(&convertedChars, strW, newLength + 1, cStr, _TRUNCATE); - return *this; + return *this; } //----------------------------------------------------------------------------- @@ -121,25 +119,25 @@ MyString &MyString::assign(const char *cStr) //----------------------------------------------------------------------------- MyString &MyString::assign(const WCHAR *cStr) { - // locals - size_t returnValue; - size_t newLength = wcslen(cStr); - size_t newReserved = (size_t)hibit((unsigned int)newLength) * 2; + // locals + size_t returnValue; + size_t newLength = wcslen(cStr); + size_t newReserved = (size_t)hibit((unsigned int)newLength) * 2; - if (reserved < newReserved) - this->~MyString(); - if (strA == nullptr) - strA = new char[newReserved]; - if (strW == nullptr) - strW = new WCHAR[newReserved]; + if (reserved < newReserved) + this->~MyString(); + if (strA == nullptr) + strA = new char[newReserved]; + if (strW == nullptr) + strW = new WCHAR[newReserved]; - reserved = newReserved; - length = newLength; + reserved = newReserved; + length = newLength; - wcscpy_s(strW, newReserved, cStr); - wcstombs_s(&returnValue, strA, newLength + 1, cStr, newLength + 1); + wcscpy_s(strW, newReserved, cStr); + wcstombs_s(&returnValue, strA, newLength + 1, cStr, newLength + 1); - return *this; + return *this; } //----------------------------------------------------------------------------- @@ -148,313 +146,248 @@ MyString &MyString::assign(const WCHAR *cStr) //----------------------------------------------------------------------------- bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned char decimalSeperator, unsigned char columnSeparator) { - // constants - const unsigned int maxValueLengthInBytes = 32; - const unsigned int bufferSize = 1000; + // constants + const unsigned int maxValueLengthInBytes = 32; + const unsigned int bufferSize = 1000; - // locals - DWORD dwBytesRead; - unsigned char buffer[bufferSize]; - unsigned char *curByte = &buffer[0]; - unsigned int curReadValue = 0; - unsigned int actualBufferSize = 0; - unsigned int curBufferPos = bufferSize; - unsigned int decimalPos = 0; - int integralValue = 0; // ACHTUNG: Erlaubt nur 8 Vorkommastellen - int fractionalValue = 0; // ACHTUNG: Erlaubt nur 8 Nachkommastellen - int exponentialValue = 1; - bool valIsNegativ = false; - bool expIsNegativ = false; - bool decimalPlace = false; - bool exponent = false; - double fractionalFactor[] = {0, - 0.1, - 0.01, - 0.001, - 0.0001, - 0.00001, - 0.000001, - 0.0000001, - 0.00000001, - 0.000000001, - 0.0000000001}; + // locals + DWORD dwBytesRead; + unsigned char buffer[bufferSize]; + unsigned char *curByte = &buffer[0]; + unsigned int curReadValue = 0; + unsigned int actualBufferSize = 0; + unsigned int curBufferPos = bufferSize; + unsigned int decimalPos = 0; + int integralValue = 0; // ACHTUNG: Erlaubt nur 8 Vorkommastellen + int fractionalValue = 0; // ACHTUNG: Erlaubt nur 8 Nachkommastellen + int exponentialValue = 1; + bool valIsNegativ = false; + bool expIsNegativ = false; + bool decimalPlace = false; + bool exponent = false; + double fractionalFactor[] = { 0, + 0.1, + 0.01, + 0.001, + 0.0001, + 0.00001, + 0.000001, + 0.0000001, + 0.00000001, + 0.000000001, + 0.0000000001 }; - // read each value - do - { + // read each value + do { - // read from buffer if necessary - if (curBufferPos >= bufferSize - maxValueLengthInBytes) - { - memcpy(&buffer[0], &buffer[curBufferPos], bufferSize - curBufferPos); - ReadFile(hFile, &buffer[bufferSize - curBufferPos], curBufferPos, &dwBytesRead, nullptr); - actualBufferSize = bufferSize - curBufferPos + dwBytesRead; - curBufferPos = 0; - curByte = &buffer[curBufferPos]; - } + // read from buffer if necessary + if (curBufferPos >= bufferSize - maxValueLengthInBytes) { + memcpy(&buffer[0], &buffer[curBufferPos], bufferSize - curBufferPos); + ReadFile(hFile, &buffer[bufferSize - curBufferPos], curBufferPos, &dwBytesRead, nullptr); + actualBufferSize = bufferSize - curBufferPos + dwBytesRead; + curBufferPos = 0; + curByte = &buffer[curBufferPos]; + } - // process current byte - switch (*curByte) - { - case '-': - if (exponent) - { - expIsNegativ = true; - } - else - { - valIsNegativ = true; - } - break; - case '+': /* ignore */ - break; - case 'e': - case 'E': - exponent = true; - decimalPlace = false; - break; - case '0': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 0; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 0; - } - else - { - integralValue *= 10; - integralValue += 0; - } - break; - case '1': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 1; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 1; - } - else - { - integralValue *= 10; - integralValue += 1; - } - break; - case '2': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 2; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 2; - } - else - { - integralValue *= 10; - integralValue += 2; - } - break; - case '3': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 3; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 3; - } - else - { - integralValue *= 10; - integralValue += 3; - } - break; - case '4': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 4; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 4; - } - else - { - integralValue *= 10; - integralValue += 4; - } - break; - case '5': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 5; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 5; - } - else - { - integralValue *= 10; - integralValue += 5; - } - break; - case '6': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 6; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 6; - } - else - { - integralValue *= 10; - integralValue += 6; - } - break; - case '7': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 7; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 7; - } - else - { - integralValue *= 10; - integralValue += 7; - } - break; - case '8': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 8; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 8; - } - else - { - integralValue *= 10; - integralValue += 8; - } - break; - case '9': - if (decimalPlace) - { - fractionalValue *= 10; - fractionalValue += 9; - decimalPos++; - } - else if (exponent) - { - exponentialValue *= 10; - exponentialValue += 9; - } - else - { - integralValue *= 10; - integralValue += 9; - } - break; - default: - if (*curByte == decimalSeperator) - { - decimalPlace = true; - exponent = false; - } - else if (*curByte == columnSeparator) - { + // process current byte + switch (*curByte) { + case '-': + if (exponent) { + expIsNegativ = true; + } else { + valIsNegativ = true; + } + break; + case '+': /* ignore */ + break; + case 'e': + case 'E': + exponent = true; + decimalPlace = false; + break; + case '0': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 0; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 0; + } else { + integralValue *= 10; + integralValue += 0; + } + break; + case '1': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 1; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 1; + } else { + integralValue *= 10; + integralValue += 1; + } + break; + case '2': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 2; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 2; + } else { + integralValue *= 10; + integralValue += 2; + } + break; + case '3': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 3; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 3; + } else { + integralValue *= 10; + integralValue += 3; + } + break; + case '4': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 4; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 4; + } else { + integralValue *= 10; + integralValue += 4; + } + break; + case '5': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 5; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 5; + } else { + integralValue *= 10; + integralValue += 5; + } + break; + case '6': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 6; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 6; + } else { + integralValue *= 10; + integralValue += 6; + } + break; + case '7': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 7; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 7; + } else { + integralValue *= 10; + integralValue += 7; + } + break; + case '8': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 8; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 8; + } else { + integralValue *= 10; + integralValue += 8; + } + break; + case '9': + if (decimalPlace) { + fractionalValue *= 10; + fractionalValue += 9; + decimalPos++; + } else if (exponent) { + exponentialValue *= 10; + exponentialValue += 9; + } else { + integralValue *= 10; + integralValue += 9; + } + break; + default: + if (*curByte == decimalSeperator) { + decimalPlace = true; + exponent = false; + } else if (*curByte == columnSeparator) { - // everything ok? - if (decimalPos > 8) - { - cout << "ERROR in function readAsciiData(): Too many digits on decimal place. Maximum is 8 !" << endl; - return false; - } + // everything ok? + if (decimalPos > 8) { + cout << "ERROR in function readAsciiData(): Too many digits on decimal place. Maximum is 8 !" << endl; + return false; + } - // calc final value - (*pData) = integralValue; - if (decimalPos) - { - (*pData) += fractionalValue * fractionalFactor[decimalPos]; - } - if (valIsNegativ) - { - (*pData) *= -1; - } - if (exponent) - { - (*pData) *= pow(10, expIsNegativ ? -1 * exponentialValue : 1); - } + // calc final value + (*pData) = integralValue; + if (decimalPos) { + (*pData) += fractionalValue * fractionalFactor[decimalPos]; + } + if (valIsNegativ) { + (*pData) *= -1; + } + if (exponent) { + (*pData) *= pow(10, expIsNegativ ? -1 * exponentialValue : 1); + } - // init - valIsNegativ = false; - expIsNegativ = false; - decimalPlace = false; - exponent = false; - integralValue = 0; - fractionalValue = 0; - exponentialValue = 1; - decimalPos = 0; + // init + valIsNegativ = false; + expIsNegativ = false; + decimalPlace = false; + exponent = false; + integralValue = 0; + fractionalValue = 0; + exponentialValue = 1; + decimalPos = 0; - // save value - pData++; - curReadValue++; - } - else - { - // do nothing - } - break; - } + // save value + pData++; + curReadValue++; + } else { + // do nothing + } + break; + } - // consider next byte - curBufferPos++; - curByte++; + // consider next byte + curBufferPos++; + curByte++; - // buffer overrun? - if (curBufferPos >= actualBufferSize) - return false; + // buffer overrun? + if (curBufferPos >= actualBufferSize) + return false; - } while (curReadValue < numValues); + } while (curReadValue < numValues); - // quit - return true; + // quit + return true; } diff --git a/src/perfect/strLib.h b/src/perfect/strLib.h index b452abdb..cde81700 100644 --- a/src/perfect/strLib.h +++ b/src/perfect/strLib.h @@ -1,9 +1,9 @@ /*********************************************************************\ - strLib.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + strLib.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef STRLIB_H @@ -24,27 +24,27 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned class MyString { private: - // variables - WCHAR *strW = nullptr; - char *strA = nullptr; - size_t length = 0; - size_t reserved = 0; + // variables + WCHAR *strW = nullptr; + char *strA = nullptr; + size_t length = 0; + size_t reserved = 0; - // functions + // functions public: - // functions - MyString(); - MyString(const char *cStr); - MyString(const WCHAR *cStr); - ~MyString(); + // functions + MyString(); + MyString(const char *cStr); + MyString(const WCHAR *cStr); + ~MyString(); - const char *c_strA(); - const WCHAR *c_strW(); - MyString &assign(const char *cStr); - MyString &assign(const WCHAR *cStr); + const char *c_strA(); + const WCHAR *c_strW(); + MyString &assign(const char *cStr); + MyString &assign(const WCHAR *cStr); - static int hibit(unsigned int n); + static int hibit(unsigned int n); }; #endif diff --git a/src/perfect/threadManager.cpp b/src/perfect/threadManager.cpp index cac5a101..7ca9d361 100644 --- a/src/perfect/threadManager.cpp +++ b/src/perfect/threadManager.cpp @@ -1,9 +1,9 @@ /********************************************************************* - threadManager.cpp - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + threadManager.cpp + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #include "threadManager.h" @@ -14,30 +14,29 @@ //----------------------------------------------------------------------------- ThreadManager::ThreadManager() { - // locals - unsigned int curThreadNo; - SYSTEM_INFO m_si = {0}; + // locals + unsigned int curThreadNo; + SYSTEM_INFO m_si = { 0 }; - GetSystemInfo(&m_si); + GetSystemInfo(&m_si); - // init default values - executionPaused = false; - executionCancelled = false; - numThreads = m_si.dwNumberOfProcessors; - hThread = new HANDLE[numThreads]; - threadId = new DWORD[numThreads]; - hBarrier = new HANDLE[numThreads]; - numThreadsPassedBarrier = 0; + // init default values + executionPaused = false; + executionCancelled = false; + numThreads = m_si.dwNumberOfProcessors; + hThread = new HANDLE[numThreads]; + threadId = new DWORD[numThreads]; + hBarrier = new HANDLE[numThreads]; + numThreadsPassedBarrier = 0; - InitializeCriticalSection(&csBarrier); - hEventBarrierPassedByEveryBody = CreateEvent(nullptr, true, false, nullptr); + InitializeCriticalSection(&csBarrier); + hEventBarrierPassedByEveryBody = CreateEvent(nullptr, true, false, nullptr); - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - hThread[curThreadNo] = nullptr; - threadId[curThreadNo] = 0; - hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); - } + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + hThread[curThreadNo] = nullptr; + threadId[curThreadNo] = 0; + hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); + } } //----------------------------------------------------------------------------- @@ -46,26 +45,25 @@ ThreadManager::ThreadManager() //----------------------------------------------------------------------------- ThreadManager::~ThreadManager() { - // locals - unsigned int curThreadNo; + // locals + unsigned int curThreadNo; - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - CloseHandle(hBarrier[curThreadNo]); - } + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + CloseHandle(hBarrier[curThreadNo]); + } - DeleteCriticalSection(&csBarrier); - CloseHandle(hEventBarrierPassedByEveryBody); + DeleteCriticalSection(&csBarrier); + CloseHandle(hEventBarrierPassedByEveryBody); - if (hBarrier != nullptr) - delete[] hBarrier; - hBarrier = nullptr; - if (hThread != nullptr) - delete[] hThread; - hThread = nullptr; - if (threadId != nullptr) - delete[] threadId; - threadId = nullptr; + if (hBarrier != nullptr) + delete[] hBarrier; + hBarrier = nullptr; + if (hThread != nullptr) + delete[] hThread; + hThread = nullptr; + if (threadId != nullptr) + delete[] threadId; + threadId = nullptr; } //----------------------------------------------------------------------------- @@ -74,45 +72,42 @@ ThreadManager::~ThreadManager() //----------------------------------------------------------------------------- void ThreadManager::waitForOtherThreads(unsigned int threadNo) { - // wait if other threads are still waiting at the barrier - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "while (numThreadsPassedBarrier>0)"; - if (numThreadsPassedBarrier > 0) - { - WaitForSingleObject(hEventBarrierPassedByEveryBody, INFINITE); - } + // wait if other threads are still waiting at the barrier + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "while (numThreadsPassedBarrier>0)"; + if (numThreadsPassedBarrier > 0) { + WaitForSingleObject(hEventBarrierPassedByEveryBody, INFINITE); + } - // a simple while (numThreadsPassedBarrier>0) {}; does not work, since the variable 'numThreadsPassedBarrier' is not updated, due to compiler optimizations + // a simple while (numThreadsPassedBarrier>0) {}; does not work, since the variable 'numThreadsPassedBarrier' is not updated, due to compiler optimizations - // set signal that barrier is reached - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "SetEvent()"; - SetEvent(hBarrier[threadNo]); + // set signal that barrier is reached + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "SetEvent()"; + SetEvent(hBarrier[threadNo]); - // enter the barrier one by one - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "EnterCriticalSection()"; - EnterCriticalSection(&csBarrier); + // enter the barrier one by one + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "EnterCriticalSection()"; + EnterCriticalSection(&csBarrier); - // if the first one which entered, then wait until other threads - if (numThreadsPassedBarrier == 0) - { - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "WaitForMultipleObjects()"; - WaitForMultipleObjects(numThreads, hBarrier, TRUE, INFINITE); - ResetEvent(hEventBarrierPassedByEveryBody); - } + // if the first one which entered, then wait until other threads + if (numThreadsPassedBarrier == 0) { + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "WaitForMultipleObjects()"; + WaitForMultipleObjects(numThreads, hBarrier, TRUE, INFINITE); + ResetEvent(hEventBarrierPassedByEveryBody); + } - // count threads which passed the barrier - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "numThreadsPassedBarrier++"; - numThreadsPassedBarrier++; + // count threads which passed the barrier + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "numThreadsPassedBarrier++"; + numThreadsPassedBarrier++; - // the last one closes the door - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "if (numThreadsPassedBarrier == numThreads) numThreadsPassedBarrier = 0"; - if (numThreadsPassedBarrier == numThreads) - { - numThreadsPassedBarrier = 0; - SetEvent(hEventBarrierPassedByEveryBody); - } + // the last one closes the door + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "if (numThreadsPassedBarrier == numThreads) numThreadsPassedBarrier = 0"; + if (numThreadsPassedBarrier == numThreads) { + numThreadsPassedBarrier = 0; + SetEvent(hEventBarrierPassedByEveryBody); + } - //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "LeaveCriticalSection()"; - LeaveCriticalSection(&csBarrier); + //cout << endl << "thread=" << threadNo << ", numThreadsPassedBarrier= " << numThreadsPassedBarrier << ": " << "LeaveCriticalSection()"; + LeaveCriticalSection(&csBarrier); } //----------------------------------------------------------------------------- @@ -121,7 +116,7 @@ void ThreadManager::waitForOtherThreads(unsigned int threadNo) //----------------------------------------------------------------------------- unsigned int ThreadManager::getNumThreads() { - return numThreads; + return numThreads; } //----------------------------------------------------------------------------- @@ -130,24 +125,21 @@ unsigned int ThreadManager::getNumThreads() //----------------------------------------------------------------------------- bool ThreadManager::setNumThreads(unsigned int newNumThreads) { - // cancel if any thread running - EnterCriticalSection(&csBarrier); - for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - if (hThread[curThreadNo]) - return false; - } - for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - CloseHandle(hBarrier[curThreadNo]); - } - numThreads = newNumThreads; - for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); - } - LeaveCriticalSection(&csBarrier); - return true; + // cancel if any thread running + EnterCriticalSection(&csBarrier); + for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + if (hThread[curThreadNo]) + return false; + } + for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + CloseHandle(hBarrier[curThreadNo]); + } + numThreads = newNumThreads; + for (unsigned int curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + hBarrier[curThreadNo] = CreateEvent(nullptr, false, false, nullptr); + } + LeaveCriticalSection(&csBarrier); + return true; } //----------------------------------------------------------------------------- @@ -156,21 +148,17 @@ bool ThreadManager::setNumThreads(unsigned int newNumThreads) //----------------------------------------------------------------------------- void ThreadManager::pauseExecution() { - for (unsigned int curThread = 0; curThread < numThreads; curThread++) - { + for (unsigned int curThread = 0; curThread < numThreads; curThread++) { - // unsuspend all threads - if (!executionPaused) - { - SuspendThread(hThread[curThread]); - // suspend all threads - } - else - { - ResumeThread(hThread[curThread]); - } - } - executionPaused = (!executionPaused); + // unsuspend all threads + if (!executionPaused) { + SuspendThread(hThread[curThread]); + // suspend all threads + } else { + ResumeThread(hThread[curThread]); + } + } + executionPaused = (!executionPaused); } //----------------------------------------------------------------------------- @@ -180,12 +168,11 @@ void ThreadManager::pauseExecution() //----------------------------------------------------------------------------- void ThreadManager::cancelExecution() { - termineAllThreads = true; - executionCancelled = true; - if (executionPaused) - { - pauseExecution(); - } + termineAllThreads = true; + executionCancelled = true; + if (executionPaused) { + pauseExecution(); + } } //----------------------------------------------------------------------------- @@ -194,7 +181,7 @@ void ThreadManager::cancelExecution() //----------------------------------------------------------------------------- void ThreadManager::uncancelExecution() { - executionCancelled = false; + executionCancelled = false; } //----------------------------------------------------------------------------- @@ -203,7 +190,7 @@ void ThreadManager::uncancelExecution() //----------------------------------------------------------------------------- bool ThreadManager::wasExecutionCancelled() { - return executionCancelled; + return executionCancelled; } //----------------------------------------------------------------------------- @@ -212,18 +199,16 @@ bool ThreadManager::wasExecutionCancelled() //----------------------------------------------------------------------------- unsigned int ThreadManager::getThreadNumber() { - // locals - DWORD curThreadId = GetCurrentThreadId(); - unsigned int curThreadNo; + // locals + DWORD curThreadId = GetCurrentThreadId(); + unsigned int curThreadNo; - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - if (curThreadId == threadId[curThreadNo]) - { - return curThreadNo; - } - } - return 0; + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + if (curThreadId == threadId[curThreadNo]) { + return curThreadNo; + } + } + return 0; } //----------------------------------------------------------------------------- @@ -232,62 +217,54 @@ unsigned int ThreadManager::getThreadNumber() //----------------------------------------------------------------------------- unsigned int ThreadManager::executeInParallel(DWORD threadProc(void *pParameter), void *pParameter, unsigned int parameterStructSize) { - // locals - unsigned int curThreadNo; - SIZE_T dwStackSize = 0; + // locals + unsigned int curThreadNo; + SIZE_T dwStackSize = 0; - // parameters ok? - if (pParameter == nullptr) - return TM_RETURN_VALUE_INVALID_PARAM; + // parameters ok? + if (pParameter == nullptr) + return TM_RETURN_VALUE_INVALID_PARAM; - // globals - termineAllThreads = false; + // globals + termineAllThreads = false; - // create threads - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { + // create threads + for (curThreadNo = 0; curThreadNo < numThreads; 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); + 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); - if (hThread[curThreadNo] == nullptr) - { - for (curThreadNo; curThreadNo > 0; curThreadNo--) - { - CloseHandle(hThread[curThreadNo - 1]); - hThread[curThreadNo - 1] = nullptr; - } - return TM_RETURN_VALUE_UNEXPECTED_ERROR; - } - } + if (hThread[curThreadNo] == nullptr) { + for (curThreadNo; curThreadNo > 0; curThreadNo--) { + CloseHandle(hThread[curThreadNo - 1]); + hThread[curThreadNo - 1] = nullptr; + } + return TM_RETURN_VALUE_UNEXPECTED_ERROR; + } + } - // start threads - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - if (!executionPaused) - ResumeThread(hThread[curThreadNo]); - } + // start threads + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + if (!executionPaused) + ResumeThread(hThread[curThreadNo]); + } - // wait for every thread to end - WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); + // wait for every thread to end + WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); - // Close all thread handles upon completion. - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - CloseHandle(hThread[curThreadNo]); - hThread[curThreadNo] = nullptr; - threadId[curThreadNo] = 0; - } + // Close all thread handles upon completion. + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + CloseHandle(hThread[curThreadNo]); + hThread[curThreadNo] = nullptr; + threadId[curThreadNo] = 0; + } - // everything ok - if (executionCancelled) - { - return TM_RETURN_VALUE_EXECUTION_CANCELLED; - } - else - { - return TM_RETURN_VALUE_OK; - } + // everything ok + if (executionCancelled) { + return TM_RETURN_VALUE_EXECUTION_CANCELLED; + } else { + return TM_RETURN_VALUE_OK; + } } //----------------------------------------------------------------------------- @@ -297,114 +274,102 @@ unsigned int ThreadManager::executeInParallel(DWORD threadProc(void *pParameter) // finalValue - this value is part of the iteration, meaning that index ranges from initialValue to finalValue including both border values //----------------------------------------------------------------------------- unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParameter, int index), - void *pParameter, - unsigned int parameterStructSize, - unsigned int scheduleType, - int initialValue, - int finalValue, - int inkrement) + void *pParameter, + unsigned int parameterStructSize, + unsigned int scheduleType, + int initialValue, + int finalValue, + int inkrement) { - // parameters ok? - if (executionCancelled == true) - return TM_RETURN_VALUE_EXECUTION_CANCELLED; - if (pParameter == nullptr) - return TM_RETURN_VALUE_INVALID_PARAM; - if (scheduleType >= TM_SCHEDULE_NUM_TYPES) - return TM_RETURN_VALUE_INVALID_PARAM; - if (inkrement == 0) - return TM_RETURN_VALUE_INVALID_PARAM; - if (abs(finalValue - initialValue) == abs(inkrement)) - return TM_RETURN_VALUE_INVALID_PARAM; + // parameters ok? + if (executionCancelled == true) + return TM_RETURN_VALUE_EXECUTION_CANCELLED; + if (pParameter == nullptr) + return TM_RETURN_VALUE_INVALID_PARAM; + if (scheduleType >= TM_SCHEDULE_NUM_TYPES) + return TM_RETURN_VALUE_INVALID_PARAM; + if (inkrement == 0) + return TM_RETURN_VALUE_INVALID_PARAM; + if (abs(finalValue - initialValue) == abs(inkrement)) + return TM_RETURN_VALUE_INVALID_PARAM; - // locals - unsigned int curThreadNo; // the threads are enumerated from 0 to numThreads-1 - int numIterations = (finalValue - initialValue) / inkrement + 1; // total number of iterations - int chunkSize = 0; // number of iterations per chunk - SIZE_T dwStackSize = 0; // initital stack size of each thread. 0 means default size ~1MB - ForLoop *forLoopParameters = new ForLoop[numThreads]; // + // locals + unsigned int curThreadNo; // the threads are enumerated from 0 to numThreads-1 + int numIterations = (finalValue - initialValue) / inkrement + 1; // total number of iterations + int chunkSize = 0; // number of iterations per chunk + SIZE_T dwStackSize = 0; // initital stack size of each thread. 0 means default size ~1MB + ForLoop *forLoopParameters = new ForLoop[numThreads]; // - // globals - termineAllThreads = false; + // globals + termineAllThreads = false; - // create threads - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { + // create threads + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { - forLoopParameters[curThreadNo].pParameter = (pParameter != nullptr ? (void *)(((char *)pParameter) + curThreadNo * parameterStructSize) : nullptr); - forLoopParameters[curThreadNo].threadManager = this; - forLoopParameters[curThreadNo].threadProc = threadProc; - forLoopParameters[curThreadNo].inkrement = inkrement; - forLoopParameters[curThreadNo].scheduleType = scheduleType; + forLoopParameters[curThreadNo].pParameter = (pParameter != nullptr ? (void *)(((char *)pParameter) + curThreadNo * parameterStructSize) : nullptr); + forLoopParameters[curThreadNo].threadManager = this; + forLoopParameters[curThreadNo].threadProc = threadProc; + forLoopParameters[curThreadNo].inkrement = inkrement; + forLoopParameters[curThreadNo].scheduleType = scheduleType; - switch (scheduleType) - { - case TM_SCHEDULE_STATIC: - chunkSize = numIterations / numThreads + (curThreadNo < numIterations % numThreads ? 1 : 0); - if (curThreadNo == 0) - { - forLoopParameters[curThreadNo].initialValue = initialValue; - } - else - { - forLoopParameters[curThreadNo].initialValue = forLoopParameters[curThreadNo - 1].finalValue + 1; - } - forLoopParameters[curThreadNo].finalValue = forLoopParameters[curThreadNo].initialValue + chunkSize - 1; - break; - case TM_SCHEDULE_DYNAMIC: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - case TM_SCHEDULE_GUIDED: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - case TM_SCHEDULE_RUNTIME: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - } + switch (scheduleType) { + case TM_SCHEDULE_STATIC: + chunkSize = numIterations / numThreads + (curThreadNo < numIterations %numThreads ? 1 : 0); + if (curThreadNo == 0) { + forLoopParameters[curThreadNo].initialValue = initialValue; + } else { + forLoopParameters[curThreadNo].initialValue = forLoopParameters[curThreadNo - 1].finalValue + 1; + } + forLoopParameters[curThreadNo].finalValue = forLoopParameters[curThreadNo].initialValue + chunkSize - 1; + break; + case TM_SCHEDULE_DYNAMIC: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + case TM_SCHEDULE_GUIDED: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + case TM_SCHEDULE_RUNTIME: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + } - // create suspended thread - hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, threadForLoop, (LPVOID)(&forLoopParameters[curThreadNo]), CREATE_SUSPENDED, &threadId[curThreadNo]); - SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL); - if (hThread[curThreadNo] == nullptr) - { - for (curThreadNo; curThreadNo > 0; curThreadNo--) - { - CloseHandle(hThread[curThreadNo - 1]); - hThread[curThreadNo - 1] = nullptr; - } - return TM_RETURN_VALUE_UNEXPECTED_ERROR; - } - //DWORD dwThreadAffinityMask = 1 << curThreadNo; - //SetThreadAffinityMask(hThread[curThreadNo], &dwThreadAffinityMask); - } + // create suspended thread + hThread[curThreadNo] = CreateThread(nullptr, dwStackSize, threadForLoop, (LPVOID)(&forLoopParameters[curThreadNo]), CREATE_SUSPENDED, &threadId[curThreadNo]); + SetThreadPriority(hThread[curThreadNo], THREAD_PRIORITY_BELOW_NORMAL); + if (hThread[curThreadNo] == nullptr) { + for (curThreadNo; curThreadNo > 0; curThreadNo--) { + CloseHandle(hThread[curThreadNo - 1]); + hThread[curThreadNo - 1] = nullptr; + } + return TM_RETURN_VALUE_UNEXPECTED_ERROR; + } + //DWORD dwThreadAffinityMask = 1 << curThreadNo; + //SetThreadAffinityMask(hThread[curThreadNo], &dwThreadAffinityMask); + } - // start threads, but don't resume if in pause mode - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - if (!executionPaused) - ResumeThread(hThread[curThreadNo]); - } + // start threads, but don't resume if in pause mode + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + if (!executionPaused) + ResumeThread(hThread[curThreadNo]); + } - // wait for every thread to end - WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); + // wait for every thread to end + WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); - // Close all thread handles upon completion. - for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) - { - CloseHandle(hThread[curThreadNo]); - hThread[curThreadNo] = nullptr; - threadId[curThreadNo] = 0; - } - delete[] forLoopParameters; + // Close all thread handles upon completion. + for (curThreadNo = 0; curThreadNo < numThreads; curThreadNo++) { + CloseHandle(hThread[curThreadNo]); + hThread[curThreadNo] = nullptr; + threadId[curThreadNo] = 0; + } + delete[] forLoopParameters; - // everything ok - if (executionCancelled) - { - return TM_RETURN_VALUE_EXECUTION_CANCELLED; - } - else - { - return TM_RETURN_VALUE_OK; - } + // everything ok + if (executionCancelled) { + return TM_RETURN_VALUE_EXECUTION_CANCELLED; + } else { + return TM_RETURN_VALUE_OK; + } } //----------------------------------------------------------------------------- @@ -413,44 +378,41 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete //----------------------------------------------------------------------------- DWORD WINAPI ThreadManager::threadForLoop(LPVOID lpParameter) { - // locals - ForLoop *forLoopParameters = (ForLoop *)lpParameter; - int index; + // locals + ForLoop *forLoopParameters = (ForLoop *)lpParameter; + int index; - switch (forLoopParameters->scheduleType) - { - case TM_SCHEDULE_STATIC: - for (index = forLoopParameters->initialValue; (forLoopParameters->inkrement < 0) ? index >= forLoopParameters->finalValue : index <= forLoopParameters->finalValue; index += forLoopParameters->inkrement) - { - switch (forLoopParameters->threadProc(forLoopParameters->pParameter, index)) - { - case TM_RETURN_VALUE_OK: - break; - case TM_RETURN_VALUE_TERMINATE_ALL_THREADS: - forLoopParameters->threadManager->termineAllThreads = true; - break; - default: - break; - } - if (forLoopParameters->threadManager->termineAllThreads) - break; - } - break; - case TM_SCHEDULE_DYNAMIC: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - case TM_SCHEDULE_GUIDED: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - case TM_SCHEDULE_RUNTIME: - return TM_RETURN_VALUE_INVALID_PARAM; - break; - } + switch (forLoopParameters->scheduleType) { + case TM_SCHEDULE_STATIC: + for (index = forLoopParameters->initialValue; (forLoopParameters->inkrement < 0) ? index >= forLoopParameters->finalValue : index <= forLoopParameters->finalValue; index += forLoopParameters->inkrement) { + switch (forLoopParameters->threadProc(forLoopParameters->pParameter, index)) { + case TM_RETURN_VALUE_OK: + break; + case TM_RETURN_VALUE_TERMINATE_ALL_THREADS: + forLoopParameters->threadManager->termineAllThreads = true; + break; + default: + break; + } + if (forLoopParameters->threadManager->termineAllThreads) + break; + } + break; + case TM_SCHEDULE_DYNAMIC: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + case TM_SCHEDULE_GUIDED: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + case TM_SCHEDULE_RUNTIME: + return TM_RETURN_VALUE_INVALID_PARAM; + break; + } - return TM_RETURN_VALUE_OK; + return TM_RETURN_VALUE_OK; } /*** To Do's ******************************************************************************** - Beschr�nkung auf 'int' kann zu �berlauf f�hren, wenn mehr states in einer layer vorliegen. - ==> Vielleicht mit class templates arbeiten + ==> Vielleicht mit class templates arbeiten *********************************************************************************************/ \ No newline at end of file diff --git a/src/perfect/threadManager.h b/src/perfect/threadManager.h index 977437cd..49613390 100644 --- a/src/perfect/threadManager.h +++ b/src/perfect/threadManager.h @@ -1,9 +1,9 @@ /*********************************************************************\ - threadManager.h - Copyright (c) Thomas Weber. All rights reserved. - Copyright (C) 2021 The Sanmill developers (see AUTHORS file) - Licensed under the MIT License. - https://github.com/madweasel/madweasels-cpp + threadManager.h + Copyright (c) Thomas Weber. All rights reserved. + Copyright (C) 2021 The Sanmill developers (see AUTHORS file) + Licensed under the MIT License. + https://github.com/madweasel/madweasels-cpp \*********************************************************************/ #ifndef THREADMANAGER_H @@ -39,114 +39,117 @@ using namespace std; // use standard library namespace class ThreadManager { private: - // structures - struct ForLoop - { - unsigned int scheduleType; - int inkrement; - int initialValue; - int finalValue; - void *pParameter; - DWORD (*threadProc) - (void *pParameter, int index); // pointer to the user function to be executed by the threads - ThreadManager *threadManager; - }; + // structures + struct ForLoop + { + unsigned int scheduleType; + int inkrement; + int initialValue; + int finalValue; + void *pParameter; + DWORD(*threadProc) + (void *pParameter, int index); // pointer to the user function to be executed by the threads + ThreadManager *threadManager; + }; - // Variables - unsigned int numThreads; // number of threads - HANDLE *hThread; // array of size 'numThreads' containing the thread handles - DWORD *threadId; // array of size 'numThreads' containing the thread ids - bool termineAllThreads; - bool executionPaused; // switch for the - bool executionCancelled; // true when cancelExecution() was called + // Variables + unsigned int numThreads; // number of threads + HANDLE *hThread; // array of size 'numThreads' containing the thread handles + DWORD *threadId; // array of size 'numThreads' containing the thread ids + bool termineAllThreads; + bool executionPaused; // switch for the + bool executionCancelled; // true when cancelExecution() was called - // barier stuff - HANDLE hEventBarrierPassedByEveryBody; - HANDLE *hBarrier; // array of size 'numThreads' containing the event handles for the barrier - unsigned int numThreadsPassedBarrier; - CRITICAL_SECTION csBarrier; + // barier stuff + HANDLE hEventBarrierPassedByEveryBody; + HANDLE *hBarrier; // array of size 'numThreads' containing the event handles for the barrier + unsigned int numThreadsPassedBarrier; + CRITICAL_SECTION csBarrier; - // functions - static DWORD WINAPI threadForLoop(LPVOID lpParameter); + // functions + static DWORD WINAPI threadForLoop(LPVOID lpParameter); public: - class ThreadVarsArrayItem - { - public: - unsigned int curThreadNo; + class ThreadVarsArrayItem + { + public: + unsigned int curThreadNo; - virtual void initializeElement(){}; - virtual void destroyElement(){}; - virtual void reduce(){}; - }; + virtual void initializeElement() + { + }; + virtual void destroyElement() + { + }; + virtual void reduce() + { + }; + }; - template - class ThreadVarsArray - { - public: - unsigned int numberOfThreads; - varType *item; + template + class ThreadVarsArray + { + public: + unsigned int numberOfThreads; + varType *item; - ThreadVarsArray(unsigned int numberOfThreads, varType &master) - { - this->numberOfThreads = numberOfThreads; - this->item = new varType[numberOfThreads]; + ThreadVarsArray(unsigned int numberOfThreads, varType &master) + { + this->numberOfThreads = numberOfThreads; + this->item = new varType[numberOfThreads]; - for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) - { - item[threadCounter].curThreadNo = threadCounter; - item[threadCounter].initializeElement(master); - item[threadCounter].curThreadNo = threadCounter; // if 'curThreadNo' is overwritten in 'initializeElement()' - } - }; + for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) { + item[threadCounter].curThreadNo = threadCounter; + item[threadCounter].initializeElement(master); + item[threadCounter].curThreadNo = threadCounter; // if 'curThreadNo' is overwritten in 'initializeElement()' + } + }; - ~ThreadVarsArray() - { - for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) - { - item[threadCounter].destroyElement(); - } - delete[] item; - }; + ~ThreadVarsArray() + { + for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) { + item[threadCounter].destroyElement(); + } + delete[] item; + }; - void *getPointerToArray() - { - return (void *)item; - }; + void *getPointerToArray() + { + return (void *)item; + }; - unsigned int getSizeOfArray() - { - return sizeof(varType); - }; + unsigned int getSizeOfArray() + { + return sizeof(varType); + }; - void reduce() - { - for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) - { - item[threadCounter].reduce(); - } - }; - }; + void reduce() + { + for (unsigned int threadCounter = 0; threadCounter < numberOfThreads; threadCounter++) { + item[threadCounter].reduce(); + } + }; + }; - // Constructor / destructor - ThreadManager(); - ~ThreadManager(); + // Constructor / destructor + ThreadManager(); + ~ThreadManager(); - // Functions - unsigned int getThreadNumber(); - unsigned int getNumThreads(); + // Functions + unsigned int getThreadNumber(); + unsigned int getNumThreads(); - bool setNumThreads(unsigned int newNumThreads); - void waitForOtherThreads(unsigned int threadNo); - void pauseExecution(); // un-/suspend all threads - void cancelExecution(); // termineAllThreads auf true - bool wasExecutionCancelled(); - void uncancelExecution(); // sets executionCancelled to false, otherwise executeParellelLoop returns immediatelly - //... void setCallBackFunction (void userFunction(void* pUser), void* pUser, DWORD milliseconds); // a user function which is called every x-milliseconds during execution between two iterations + bool setNumThreads(unsigned int newNumThreads); + void waitForOtherThreads(unsigned int threadNo); + void pauseExecution(); // un-/suspend all threads + void cancelExecution(); // termineAllThreads auf true + bool wasExecutionCancelled(); + void uncancelExecution(); // sets executionCancelled to false, otherwise executeParellelLoop returns immediatelly + //... void setCallBackFunction (void userFunction(void* pUser), void* pUser, DWORD milliseconds); // a user function which is called every x-milliseconds during execution between two iterations - // execute - unsigned int executeInParallel(DWORD threadProc(void *pParameter), void *pParameter, unsigned int parameterStructSize); - unsigned int executeParallelLoop(DWORD threadProc(void *pParameter, int index), void *pParameter, unsigned int parameterStructSize, unsigned int scheduleType, int initialValue, int finalValue, int inkrement); + // execute + unsigned int executeInParallel(DWORD threadProc(void *pParameter), void *pParameter, unsigned int parameterStructSize); + unsigned int executeParallelLoop(DWORD threadProc(void *pParameter, int index), void *pParameter, unsigned int parameterStructSize, unsigned int scheduleType, int initialValue, int finalValue, int inkrement); }; #endif