perfect: Refactor format

This commit is contained in:
Calcitem 2021-01-22 23:05:00 +08:00
parent 4674670459
commit 15d35f55c0
10 changed files with 279 additions and 84 deletions

View File

@ -37,7 +37,8 @@ BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSize
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);
hFile = CreateFileA(fileName,
GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file successfully
if (hFile == INVALID_HANDLE_VALUE) {
@ -92,7 +93,10 @@ 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]);
writeDataToFile(hFile,
curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo],
bytesInWriteBuffer[threadNo],
&writeBuffer[threadNo * bufferSize + 0]);
bytesInWriteBuffer[threadNo] = 0;
}
@ -180,7 +184,10 @@ bool BufferedFile::writeBytes(unsigned int numBytes, unsigned char *pData)
// writeBytes()
//
//-----------------------------------------------------------------------------
bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, 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)
@ -192,9 +199,13 @@ bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, u
// locals
// if buffer full or not sequential write operation write buffer to file
if (bytesInWriteBuffer[threadNo] && (positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) {
if (bytesInWriteBuffer[threadNo] &&
(positionInFile != curWritingPointer[threadNo] || bytesInWriteBuffer[threadNo] + numBytes >= bufferSize)) {
writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]);
writeDataToFile(hFile,
curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo],
bytesInWriteBuffer[threadNo],
&writeBuffer[threadNo * bufferSize + 0]);
bytesInWriteBuffer[threadNo] = 0;
}
@ -220,7 +231,10 @@ bool BufferedFile::readBytes(unsigned int numBytes, unsigned char *pData)
// takeBytes()
//
//-----------------------------------------------------------------------------
bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, 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)
@ -231,10 +245,12 @@ bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, un
// 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));
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]]);
readDataFromFile(hFile, positionInFile, bytesInReadBuffer[threadNo],
&readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]]);
}
memcpy(pData, &readBuffer[threadNo * bufferSize + bufferSize - bytesInReadBuffer[threadNo]], numBytes);

View File

@ -26,7 +26,9 @@ CyclicArray::CyclicArray(unsigned int blockSizeInBytes, unsigned int numberOfBlo
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);
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) {
@ -240,7 +242,8 @@ bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded)
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);
hLoadFile = CreateFileA(fileName,
GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully
if (hLoadFile == INVALID_HANDLE_VALUE) {
@ -308,7 +311,8 @@ bool CyclicArray::saveFile(const char *fileName)
}
// 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);
hSaveFile = CreateFileA(fileName,
GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
// opened file succesfully
if (hSaveFile == INVALID_HANDLE_VALUE) {

View File

@ -97,7 +97,8 @@ bool Mill::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int
//-----------------------------------------------------------------------------
// setUpCalcPossibleMoves()
// Calculates and set the number of possible moves for the passed player considering the game state stored in the 'board' variable.
// Calculates and set the number of possible moves for the passed player
// considering the game state stored in the 'board' variable.
//-----------------------------------------------------------------------------
void Mill::setUpCalcPossibleMoves(Player *player)
{
@ -144,7 +145,8 @@ void Mill::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbou
int rowOwner = field.board[stone];
// mill closed ?
if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) {
if (rowOwner != field.squareIsFree &&
field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) {
field.stonePartOfMill[stone]++;
field.stonePartOfMill[firstNeighbour]++;
@ -213,7 +215,11 @@ bool Mill::putPiece(unsigned int pos, int player)
// ... 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;
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;
@ -221,7 +227,8 @@ bool Mill::putPiece(unsigned int pos, int player)
}
// when opponent is unable to move than current player has won
if ((!field.curPlayer->numPossibleMoves) && (!field.settingPhase) && (!field.stoneMustBeRemoved) && (field.curPlayer->numStones > 3))
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;
@ -457,14 +464,19 @@ void Mill::calcPossibleMoves(Player *player)
// setWarningAndMill()
//
//-----------------------------------------------------------------------------
void Mill::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour, bool isNewStone)
void Mill::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;
// mill closed ?
if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == rowOwner && field.board[secondNeighbour] == rowOwner) {
if (rowOwner != field.squareIsFree &&
field.board[firstNeighbour] == rowOwner &&
field.board[secondNeighbour] == rowOwner) {
field.stonePartOfMill[stone]++;
field.stonePartOfMill[firstNeighbour]++;
@ -474,9 +486,14 @@ void Mill::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour, un
}
//warning ?
if (rowOwner != field.squareIsFree && field.board[firstNeighbour] == field.squareIsFree && field.board[secondNeighbour] == rowOwner)
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)
if (rowOwner != field.squareIsFree &&
field.board[secondNeighbour] == field.squareIsFree &&
field.board[firstNeighbour] == rowOwner)
field.warnings[secondNeighbour] |= rowOwnerWarning;
}
@ -732,7 +749,8 @@ bool Mill::compareWithField(fieldStruct *compareField)
ret = false;
}
// if (board.stoneMoveAble[i][j] != compareField->stoneMoveAble[i][j]) { cout << "error - stoneMoveAble differs!" << endl; ret = false; }
// if (board.stoneMoveAble[i][j] != compareField->stoneMoveAble[i][j])
// { cout << "error - stoneMoveAble differs!" << endl; ret = false; }
if (field.neighbour[i][j / 2][j % 2] != compareField->neighbour[i][j / 2][j % 2]) {
cout << "error - neighbour differs!" << endl;
@ -838,10 +856,14 @@ void Mill::undoMove(void)
void Mill::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;
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;
numWhiteStonesResting =
fieldStruct::numStonesPerPlayer - field.oppPlayer->numStonesMissing - field.oppPlayer->numStones;
numBlackStonesResting =
fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones;
}
}

View File

@ -58,7 +58,10 @@ private:
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);
void setWarningAndMill(unsigned int stone,
unsigned int firstNeighbour,
unsigned int secondNeighbour,
bool isNewStone);
public:
// Constructor / destructor

View File

@ -23,8 +23,10 @@ void fieldStruct::printBoard()
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 << "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";
@ -234,7 +236,11 @@ void fieldStruct::deleteBoard()
// setConnection()
//
//-----------------------------------------------------------------------------
inline void fieldStruct::setConnection(unsigned int index, int firstDirection, int secondDirection, int thirdDirection, int fourthDirection)
inline void fieldStruct::setConnection(unsigned int index,
int firstDirection,
int secondDirection,
int thirdDirection,
int fourthDirection)
{
connectedSquare[index][0] = firstDirection;
connectedSquare[index][1] = secondDirection;
@ -246,7 +252,11 @@ inline void fieldStruct::setConnection(unsigned int index, int firstDirection, i
// setNeighbour()
//
//-----------------------------------------------------------------------------
inline void fieldStruct::setNeighbour(unsigned int index, unsigned int firstNeighbour0, unsigned int secondNeighbour0, unsigned int firstNeighbour1, unsigned int secondNeighbour1)
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;

View File

@ -80,8 +80,16 @@ public:
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);
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

View File

@ -97,7 +97,8 @@ bool MiniMax::falseOrStop()
//-----------------------------------------------------------------------------
// getBestChoice()
// Returns the best choice if the database has been opened and calculates the best choice for that if database is not open.
// Returns the best choice if the database has been opened and
// calculates the best choice for that if database is not open.
//-----------------------------------------------------------------------------
void *MiniMax::getBestChoice(unsigned int tilLevel, unsigned int *choice, unsigned int maximumNumberOfBranches)
{
@ -155,21 +156,22 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepLayer)
threadManager.uncancelExecution();
arrayInfos.vectorArrays.resize(ArrayInfo::numArrayTypes * skvfHeader.numLayers, arrayInfos.listArrays.end());
// calc layer after layer, beginning with the last one
// calculate layer after layer, beginning with the last one
for (curCalculatedLayer = 0; curCalculatedLayer < skvfHeader.numLayers; curCalculatedLayer++) {
// 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)
// don't calculate if neither the layer nor the partner layer has any knots
if (layerStats[curCalculatedLayer].knotsInLayer == 0 &&
layerStats[layerStats[curCalculatedLayer].partnerLayer].knotsInLayer == 0)
continue;
// calc
// calculate
abortCalculation = (!calcLayer(curCalculatedLayer));
// relase memory
// release memory
unloadAllLayers();
unloadAllPlyInfos();
@ -189,7 +191,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepLayer)
return;
if (!abortCalculation) {
// calc layer statistics
// calculate layer statistics
calcLayerStatistics((char *)"statistics.txt");
// save header
@ -199,7 +201,7 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepLayer)
saveHeader(&plyInfoHeader, plyInfos);
}
// free mem
// free memory
curCalculationActionId = MM_ACTION_NONE;
} else {
PRINT(1, this, "\nThe database is already fully calculated.\n");
@ -224,7 +226,7 @@ bool MiniMax::calcLayer(unsigned int layerNumber)
// moves can be done reverse, leading to too depth searching trees
if (shallRetroAnalysisBeUsed(layerNumber)) {
// calc values for all states of layer
// calculate values for all states of layer
layersToCalc.push_back(layerNumber);
if (layerNumber != layerStats[layerNumber].partnerLayer)
layersToCalc.push_back(layerStats[layerNumber].partnerLayer);

View File

@ -247,7 +247,7 @@ public:
void updateArray(unsigned int layerNumber, unsigned int type);
};
/*** public functions ***************************************************************************************************************************/
/*** public functions *********************************************************************************************/
// Constructor / destructor
MiniMax();
@ -298,7 +298,10 @@ public:
;
}; // is called once before building the tree
virtual unsigned int *getPossibilities(unsigned int threadNo, unsigned int *numPossibilities, bool *opponentsMove, void **pPossibilities)
virtual unsigned int *getPossibilities(unsigned int threadNo,
unsigned int *numPossibilities,
bool *opponentsMove,
void **pPossibilities)
{
while (true)
;
@ -311,17 +314,30 @@ public:
;
};
virtual void storeValueOfMove(unsigned int threadNo, unsigned int idPossibility, void *pPossibilities, TwoBit value, unsigned int *freqValuesSubMoves, PlyInfoVarType plyInfo)
virtual void storeValueOfMove(unsigned int threadNo,
unsigned int idPossibility,
void *pPossibilities,
TwoBit value,
unsigned int *freqValuesSubMoves,
PlyInfoVarType plyInfo)
{
};
virtual void move(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void **pBackup, void *pPossibilities)
virtual void move(unsigned int threadNo,
unsigned int idPossibility,
bool opponentsMove,
void **pBackup,
void *pPossibilities)
{
while (true)
;
};
virtual void undo(unsigned int threadNo, unsigned int idPossibility, bool opponentsMove, void *pBackup, void *pPossibilities)
virtual void undo(unsigned int threadNo,
unsigned int idPossibility,
bool opponentsMove,
void *pBackup,
void *pPossibilities)
{
while (true)
;
@ -384,13 +400,17 @@ public:
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)
virtual unsigned int getLayerAndStateNumber(unsigned int threadNo,
unsigned int &layerNum,
unsigned int &stateNumber)
{
while (true)
;
@ -403,7 +423,9 @@ public:
return 0;
};
virtual void getSymStateNumWithDoubles(unsigned int threadNo, unsigned int *numSymmetricStates, unsigned int **symStateNumbers)
virtual void getSymStateNumWithDoubles(unsigned int threadNo,
unsigned int *numSymmetricStates,
unsigned int **symStateNumbers)
{
while (true)
;
@ -440,7 +462,7 @@ public:
};
private:
/*** classes for testing ********************************************************************************************************************/
/*** classes for testing *****************************************************************************************/
struct TestLayersVars
{
@ -453,9 +475,9 @@ private:
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
struct AlphaBetaThreadVars // thread specific variables for each thread in the alpha beta algorithm
{
long long numStatesToProcess; // Number of states in 'statesToProcess' which have to be processed
unsigned int threadNo;
@ -531,7 +553,11 @@ private:
{
};
InitAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
InitAlphaBetaVars(MiniMax *pMiniMax,
AlphaBetaGlobalVars *alphaBetaVars,
unsigned int layerNumber,
BufferedFile *initArray,
bool initAlreadyDone) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
{
this->bufferedFile = initArray;
this->initAlreadyDone = initAlreadyDone;
@ -558,7 +584,9 @@ private:
{
};
RunAlphaBetaVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
RunAlphaBetaVars(MiniMax *pMiniMax,
AlphaBetaGlobalVars *alphaBetaVars,
unsigned int layerNumber) : AlphaBetaDefaultThreadVars(pMiniMax, alphaBetaVars, layerNumber)
{
initializeElement(*this);
};
@ -582,7 +610,7 @@ private:
};
};
/*** classes for the retro analysis ***************************************************************************************************************************/
/*** classes for the retro analysis *******************************************************************************/
struct RetroAnalysisQueueState
{
@ -651,7 +679,11 @@ private:
{
};
InitRetroAnalysisVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber, BufferedFile *initArray, bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
InitRetroAnalysisVars(MiniMax *pMiniMax,
retroAnalysisGlobalVars *retroVars,
unsigned int layerNumber,
BufferedFile *initArray,
bool initAlreadyDone) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
{
this->bufferedFile = initArray;
this->initAlreadyDone = initAlreadyDone;
@ -676,7 +708,9 @@ private:
{
};
AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
AddNumSuccedorsVars(MiniMax *pMiniMax,
retroAnalysisGlobalVars *retroVars,
unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
{
};
@ -691,7 +725,7 @@ private:
};
};
/*** private variables ***************************************************************************************************************************/
/*** private variables ********************************************************************************************/
// variables, which are constant during database calculation
int verbosity = 2; // output detail level. default is 2
@ -730,7 +764,7 @@ private:
// compressorClass * compressor = nullptr;
// unsigned int compressionAlgorithmnId = 0; // 0 or one of the COMPRESSOR_ALG_... constants
// database io operations per second
// database I/O operations per second
long long numReadSkvOperations = 0; // number of read operations done since start of the program
long long numWriteSkvOperations = 0; // number of write operations done since start of the program
long long numReadPlyOperations = 0; // number of read operations done since start of the program
@ -751,7 +785,12 @@ private:
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 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);
@ -765,17 +804,36 @@ private:
static DWORD testLayerThreadProc(void *pParameter, int index);
static DWORD testSetSituationThreadProc(void *pParameter, int index);
// Alpha-Beta-Algorithmn
// Alpha-Beta-Algorithm
bool calcKnotValuesByAlphaBeta(unsigned int layerNumber);
bool initAlphaBeta(AlphaBetaGlobalVars &retroVars);
bool runAlphaBeta(AlphaBetaGlobalVars &retroVars);
void letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, float alpha, float beta);
bool alphaBetaTryDataBase(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int &layerNumber, unsigned int &stateNumber);
void alphaBetaTryPossibilites(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int *idPossibility, void *pPossibilities, unsigned int &maxWonfreqValuesSubMoves, float &alpha, float &beta);
bool alphaBetaTryDataBase(Knot *knot,
RunAlphaBetaVars *rabVars,
unsigned int tilLevel,
unsigned int &layerNumber, unsigned int &stateNumber);
void alphaBetaTryPossibilites(Knot *knot,
RunAlphaBetaVars *rabVars,
unsigned int tilLevel,
unsigned int *idPossibility,
void *pPossibilities,
unsigned int &maxWonfreqValuesSubMoves,
float &alpha,
float &beta);
void alphaBetaCalcPlyInfo(Knot *knot);
void alphaBetaCalcKnotValue(Knot *knot);
void alphaBetaChooseBestMove(Knot *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);
void alphaBetaChooseBestMove(Knot *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);
@ -785,7 +843,10 @@ private:
bool prepareCountArrays(retroAnalysisGlobalVars &retroVars);
bool calcNumSuccedors(retroAnalysisGlobalVars &retroVars);
bool performRetroAnalysis(retroAnalysisGlobalVars &retroVars);
bool addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAnalysisThreadVars &threadVars, unsigned int plyNumber, StateAdress *pState);
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;

View File

@ -10,7 +10,7 @@
#define MINIMAXWIN_H
// Windows Header Files:
#include "miniMax\\miniMax.h"
#include "miniMax.h"
#include <queue>
#include <thread>
#include <mutex>

View File

@ -27,7 +27,7 @@ bool MiniMax::calcKnotValuesByAlphaBeta(unsigned int layerNumber)
return false;
}
// run alpha-beta algorithmn
// run alpha-beta algorithm
PRINT(2, this, " Bytes in memory: " << memoryUsed2 << endl);
if (!runAlphaBeta(alphaBetaVars)) {
return false;
@ -44,7 +44,12 @@ bool MiniMax::calcKnotValuesByAlphaBeta(unsigned int layerNumber)
// saveKnotValueInDatabase()
//
//-----------------------------------------------------------------------------
void MiniMax::alphaBetaSaveInDatabase(unsigned int threadNo, unsigned int layerNumber, unsigned int stateNumber, TwoBit knotValue, PlyInfoVarType plyValue, bool invertValue)
void MiniMax::alphaBetaSaveInDatabase(unsigned int threadNo,
unsigned int layerNumber,
unsigned int stateNumber,
TwoBit knotValue,
PlyInfoVarType plyValue,
bool invertValue)
{
// locals
unsigned int *symStateNumbers = nullptr;
@ -107,7 +112,8 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
ssInvArrayDirectory.str("");
ssInvArrayDirectory << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates";
ssInvArrayFilePath.str("");
ssInvArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") << "invalidStates\\invalidStatesOfLayer" << alphaBetaVars.layerNumber << ".dat";
ssInvArrayFilePath << fileDirectory << (fileDirectory.size() ? "\\" : "") <<
"invalidStates\\invalidStatesOfLayer" << alphaBetaVars.layerNumber << ".dat";
// does initialization file exist ?
CreateDirectoryA(ssInvArrayDirectory.str().c_str(), nullptr);
@ -124,10 +130,21 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0;
alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0;
alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0;
ThreadManager::ThreadVarsArray<InitAlphaBetaVars> tva(threadManager.getNumThreads(), (InitAlphaBetaVars &)InitAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber, invalidArray, initAlreadyDone));
ThreadManager::ThreadVarsArray<InitAlphaBetaVars> tva(threadManager.getNumThreads(),
(InitAlphaBetaVars &)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)) {
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:
@ -183,12 +200,16 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index)
// 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(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)) {
if (!iabVars->bufferedFile->readBytes(iabVars->curThreadNo,
index * sizeof(TwoBit),
sizeof(TwoBit),
(unsigned char *)&curStateValue)) {
PRINT(0, m, "ERROR: initArray->takeBytes() failed");
return m->falseOrStop();
}
@ -218,7 +239,10 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index)
// write data to file
if (!iabVars->initAlreadyDone) {
if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo, index * sizeof(TwoBit), sizeof(TwoBit), (unsigned char *)&curStateValue)) {
if (!iabVars->bufferedFile->writeBytes(iabVars->curThreadNo,
index * sizeof(TwoBit),
sizeof(TwoBit),
(unsigned char *)&curStateValue)) {
PRINT(0, m, "ERROR: bufferedFile->writeBytes failed!");
return m->falseOrStop();
}
@ -242,13 +266,21 @@ bool MiniMax::runAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_LOST] = 0;
alphaBetaVars.statsValueCounter[SKV_VALUE_GAME_DRAWN] = 0;
alphaBetaVars.statsValueCounter[SKV_VALUE_INVALID] = 0;
ThreadManager::ThreadVarsArray<RunAlphaBetaVars> tva(threadManager.getNumThreads(), (RunAlphaBetaVars &)RunAlphaBetaVars(this, &alphaBetaVars, alphaBetaVars.layerNumber));
ThreadManager::ThreadVarsArray<RunAlphaBetaVars> tva(threadManager.getNumThreads(),
(RunAlphaBetaVars &)RunAlphaBetaVars(this,
&alphaBetaVars,
alphaBetaVars.layerNumber));
// 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)) {
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:
@ -296,7 +328,9 @@ DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index)
// 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(2, m,
" Processed " << m->numStatesProcessed << " of " <<
m->layerStats[curState.layerNumber].knotsInLayer << " states");
}
// Version 10: state already calculated? if so leave.
@ -360,7 +394,10 @@ void MiniMax::letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int
return;
// get number of possibilities
idPossibility = getPossibilities(rabVars->curThreadNo, &knot->numPossibilities, &knot->isOpponentLevel, &pPossibilities);
idPossibility = getPossibilities(rabVars->curThreadNo,
&knot->numPossibilities,
&knot->isOpponentLevel,
&pPossibilities);
// unable to move
if (knot->numPossibilities == 0) {
@ -380,7 +417,14 @@ void MiniMax::letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int
// movement is possible
} else {
// move, letTreeGroe, undo
alphaBetaTryPossibilites(knot, rabVars, tilLevel, idPossibility, pPossibilities, maxWonfreqValuesSubMoves, alpha, beta);
alphaBetaTryPossibilites(knot,
rabVars,
tilLevel,
idPossibility,
pPossibilities,
maxWonfreqValuesSubMoves,
alpha,
beta);
// calculate value of knot - its the value of the best branch
alphaBetaCalcKnotValue(knot);
@ -394,7 +438,12 @@ void MiniMax::letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int
// 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);
alphaBetaSaveInDatabase(rabVars->curThreadNo,
layerNumber,
stateNumber,
knot->shortValue,
knot->plyInfo,
knot->isOpponentLevel);
}
}
@ -405,7 +454,11 @@ void MiniMax::letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int
// 2 - Look into database if knot value and ply info are already calculated. If so sets knot->shortValue, knot->floatValue and knot->plyInfo.
// CAUTION: knot->isOpponentLevel must be set and valid.
//-----------------------------------------------------------------------------
bool MiniMax::alphaBetaTryDataBase(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int tilLevel, unsigned int &layerNumber, unsigned int &stateNumber)
bool MiniMax::alphaBetaTryDataBase(Knot *knot,
RunAlphaBetaVars *rabVars,
unsigned int tilLevel,
unsigned int &layerNumber,
unsigned int &stateNumber)
{
// locals
bool invalidLayerOrStateNumber;
@ -416,12 +469,19 @@ bool MiniMax::alphaBetaTryDataBase(Knot *knot, RunAlphaBetaVars *rabVars, unsign
// use database ?
if (hFilePlyInfo != nullptr && hFileShortKnotValues != nullptr && (calcDatabase || layerInDatabase)) {
// situation already existed in database ?
readKnotValueFromDatabase(rabVars->curThreadNo, layerNumber, stateNumber, shortKnotValue, invalidLayerOrStateNumber, subLayerInDatabaseAndCompleted);
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)) {
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;
@ -430,11 +490,20 @@ bool MiniMax::alphaBetaTryDataBase(Knot *knot, RunAlphaBetaVars *rabVars, unsign
// 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(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) {
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)