prefect: Rename position to mill and add blank lines

This commit is contained in:
Calcitem 2021-01-21 00:15:08 +08:00
parent 6b610ee3d6
commit b938e0fd66
25 changed files with 384 additions and 228 deletions

View File

@ -33,6 +33,7 @@ BufferedFile::BufferedFile(unsigned int numberOfThreads, unsigned int bufferSize
bytesInReadBuffer[curThread] = 0;
bytesInWriteBuffer[curThread] = 0;
}
InitializeCriticalSection(&csIO);
// Open Database-File (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS)
@ -80,6 +81,7 @@ long long BufferedFile::getFileSize()
LARGE_INTEGER liFileSize;
GetFileSizeEx(hFile, &liFileSize);
fileSize = liFileSize.QuadPart;
return fileSize;
}
@ -93,6 +95,7 @@ bool BufferedFile::flushBuffers()
writeDataToFile(hFile, curWritingPointer[threadNo] - bytesInWriteBuffer[threadNo], bytesInWriteBuffer[threadNo], &writeBuffer[threadNo * bufferSize + 0]);
bytesInWriteBuffer[threadNo] = 0;
}
return true;
}
@ -109,9 +112,11 @@ void BufferedFile::writeDataToFile(HANDLE hFile, long long offset, unsigned int
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;
@ -124,6 +129,7 @@ void BufferedFile::writeDataToFile(HANDLE hFile, long long offset, unsigned int
<< "WriteFile Failed!";
}
}
LeaveCriticalSection(&csIO);
}
@ -140,9 +146,11 @@ void BufferedFile::readDataFromFile(HANDLE hFile, long long offset, unsigned int
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;
@ -155,6 +163,7 @@ void BufferedFile::readDataFromFile(HANDLE hFile, long long offset, unsigned int
<< "ReadFile Failed!";
}
}
LeaveCriticalSection(&csIO);
}
@ -176,6 +185,7 @@ bool BufferedFile::writeBytes(unsigned int threadNo, long long positionInFile, u
// parameters ok?
if (threadNo >= numThreads)
return false;
if (pData == nullptr)
return false;
@ -215,6 +225,7 @@ bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, un
// parameters ok?
if (threadNo >= numThreads)
return false;
if (pData == nullptr)
return false;
@ -225,6 +236,7 @@ bool BufferedFile::readBytes(unsigned int threadNo, long long positionInFile, un
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;

View File

@ -148,6 +148,7 @@ bool CyclicArray::addBytes(unsigned int numBytes, unsigned char *pData)
// set pointer to beginnig of writing block
curWritingPointer = writingBlock;
curWritingBlock = (curWritingBlock + 1) % numBlocks;
if (curWritingBlock == 0)
readWriteInSameRound = false;
}
@ -194,7 +195,6 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData)
// load next block?
if (curReadingPointer == readingBlock + blockSize) {
// go to next block
curReadingBlock = (curReadingBlock + 1) % numBlocks;
if (curReadingBlock == 0)
@ -204,7 +204,6 @@ bool CyclicArray::takeBytes(unsigned int numBytes, unsigned char *pData)
if (curReadingBlock == curWritingBlock) {
curReadingPointer = writingBlock;
} else {
// set pointer to beginnig of reading block
curReadingPointer = readingBlock;
@ -269,7 +268,6 @@ bool CyclicArray::loadFile(const char *fileName, LONGLONG &numBytesLoaded)
//
for (curBlock = 0; curBlock < numBlocksInFile - 1; curBlock++, curOffset += blockSize) {
// load data from file
readDataFromFile(hLoadFile, curOffset, blockSize, dataInFile);
@ -323,7 +321,6 @@ bool CyclicArray::saveFile(const char *fileName)
dataInFile = new unsigned char[blockSize];
do {
// copy current block
if (curBlock == curWritingBlock && curBlock == curReadingBlock) {
pointer = curReadingPointer;

View File

@ -1,7 +1,7 @@
#include <cstdio>
#include <iostream>
#include <windows.h>
#include "position.h"
#include "mill.h"
#include "miniMaxAI.h"
#include "randomAI.h"
#include "perfectAI.h"
@ -26,7 +26,7 @@ int main(void)
bool playerTwoHuman = false;
char ch[100];
unsigned int pushFrom, pushTo;
Position *pos = new Position();
Mill *pos = new Mill();
PerfectAI *ai = new PerfectAI(databaseDirectory);
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
@ -48,17 +48,20 @@ int main(void)
#endif // SELF_PLAY
if (calculateDatabase) {
// calculate
ai->calculateDatabase(MAX_DEPTH_OF_TREE, false);
// test database
cout << endl
<< "Begin test starting from layer: ";
startTestFromLayer;
cout << endl
<< "End test at layer: ";
endTestAtLayer;
ai->testLayers(startTestFromLayer, endTestAtLayer);
} else {
@ -134,12 +137,12 @@ int main(void)
break;
}
} while (pos->do_move(pushFrom, pushTo) == false);
} while (pos->doMove(pushFrom, pushTo) == false);
// Computer
} else {
cout << "\n";
pos->do_move(pushFrom, pushTo);
pos->doMove(pushFrom, pushTo);
}
} while (pos->getWinner() == 0);

View File

@ -1,18 +1,18 @@
/*********************************************************************
Position.cpp
Mill.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"
#include "mill.h"
//-----------------------------------------------------------------------------
// Name: Position()
// Desc: Position class constructor
// Name: Mill()
// Desc: Mill class constructor
//-----------------------------------------------------------------------------
Position::Position()
Mill::Mill()
{
srand((unsigned)time(nullptr));
@ -27,19 +27,19 @@ Position::Position()
}
//-----------------------------------------------------------------------------
// Name: ~Position()
// Desc: Position class destructor
// Name: ~Mill()
// Desc: Mill class destructor
//-----------------------------------------------------------------------------
Position::~Position()
Mill::~Mill()
{
exit();
}
//-----------------------------------------------------------------------------
// Name: deleteArrays()
// Desc: Deletes all arrays the Position class has created.
// Desc: Deletes all arrays the Mill class has created.
//-----------------------------------------------------------------------------
void Position::exit()
void Mill::exit()
{
SAFE_DELETE_ARRAY(moveLogFrom);
SAFE_DELETE_ARRAY(moveLogTo);
@ -50,9 +50,9 @@ void Position::exit()
//-----------------------------------------------------------------------------
// Name: beginNewGame()
// Desc: Reinitializes the Position object.
// Desc: Reinitializes the Mill object.
//-----------------------------------------------------------------------------
void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer)
void Mill::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer)
{
// free mem
exit();
@ -67,6 +67,7 @@ void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int c
} else {
beginningPlayer = (rand() % 2) ? field.playerOne : field.playerTwo;
}
field.curPlayer->id = beginningPlayer;
field.oppPlayer->id = (field.curPlayer->id == field.playerTwo) ? field.playerOne : field.playerTwo;
@ -85,7 +86,7 @@ void Position::beginNewGame(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int c
// Name: startSettingPhase()
// Desc:
//-----------------------------------------------------------------------------
bool Position::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer, bool settingPhase)
bool Mill::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI, int currentPlayer, bool settingPhase)
{
beginNewGame(firstPlayerAI, secondPlayerAI, currentPlayer);
@ -98,7 +99,7 @@ bool Position::startSettingPhase(MillAI *firstPlayerAI, MillAI *secondPlayerAI,
// Name: setUpCalcPossibleMoves()
// Desc: Calculates and set the number of possible moves for the passed player considering the game state stored in the 'board' variable.
//-----------------------------------------------------------------------------
void Position::setUpCalcPossibleMoves(Player *player)
void Mill::setUpCalcPossibleMoves(Player *player)
{
// locals
unsigned int i, j, k, movingDirection;
@ -137,7 +138,7 @@ void Position::setUpCalcPossibleMoves(Player *player)
// Name: setUpSetWarningAndMill()
// Desc:
//-----------------------------------------------------------------------------
void Position::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour)
void Mill::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeighbour, unsigned int secondNeighbour)
{
// locals
int rowOwner = field.board[stone];
@ -152,10 +153,10 @@ void Position::setUpSetWarningAndMill(unsigned int stone, unsigned int firstNeig
}
//-----------------------------------------------------------------------------
// Name: put_piece()
// Name: putPiece()
// Desc: Put a stone onto the board during the setting phase.
//-----------------------------------------------------------------------------
bool Position::put_piece(unsigned int pos, int player)
bool Mill::putPiece(unsigned int pos, int player)
{
// locals
unsigned int i;
@ -237,7 +238,7 @@ bool Position::put_piece(unsigned int pos, int player)
// Name: settingPhaseHasFinished()
// Desc: This function has to be called when the setting phase has finished.
//-----------------------------------------------------------------------------
bool Position::settingPhaseHasFinished()
bool Mill::settingPhaseHasFinished()
{
// remember initialField
field.copyBoard(&initialField);
@ -249,7 +250,7 @@ bool Position::settingPhaseHasFinished()
// Name: getField()
// Desc: Copy the current board state into the array 'pField'.
//-----------------------------------------------------------------------------
bool Position::getField(int *pField)
bool Mill::getField(int *pField)
{
unsigned int index;
@ -271,7 +272,7 @@ bool Position::getField(int *pField)
// Name: getLog()
// Desc: Copy the whole history of moves into the passed arrays, which must be of size [MAX_NUM_MOVES].
//-----------------------------------------------------------------------------
void Position::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned int *to)
void Mill::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned int *to)
{
unsigned int index;
@ -287,7 +288,7 @@ void Position::getLog(unsigned int &numMovesDone, unsigned int *from, unsigned i
// Name: setNextPlayer()
// Desc: Current player and opponent player are switched in the board struct.
//-----------------------------------------------------------------------------
void Position::setNextPlayer()
void Mill::setNextPlayer()
{
Player *tmpPlayer;
@ -300,7 +301,7 @@ void Position::setNextPlayer()
// Name: isCurrentPlayerHuman()
// Desc: Returns true if the current player is not assigned to an AI.
//-----------------------------------------------------------------------------
bool Position::isCurrentPlayerHuman()
bool Mill::isCurrentPlayerHuman()
{
if (field.curPlayer->id == field.playerOne)
return (playerOneAI == nullptr) ? true : false;
@ -312,7 +313,7 @@ bool Position::isCurrentPlayerHuman()
// Name: isOpponentPlayerHuman()
// Desc: Returns true if the opponent player is not assigned to an AI.
//-----------------------------------------------------------------------------
bool Position::isOpponentPlayerHuman()
bool Mill::isOpponentPlayerHuman()
{
if (field.oppPlayer->id == field.playerOne)
return (playerOneAI == nullptr) ? true : false;
@ -324,7 +325,7 @@ bool Position::isOpponentPlayerHuman()
// Name: setAI()
// Desc: Assigns an AI to a player.
//-----------------------------------------------------------------------------
void Position::setAI(int player, MillAI *AI)
void Mill::setAI(int player, MillAI *AI)
{
if (player == field.playerOne) {
playerOneAI = AI;
@ -338,7 +339,7 @@ void Position::setAI(int player, MillAI *AI)
// Name: getChoiceOfSpecialAI()
// Desc: Returns the move the passed AI would do.
//-----------------------------------------------------------------------------
void Position::getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo)
void Mill::getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo)
{
fieldStruct theField;
*pushFrom = field.size;
@ -354,7 +355,7 @@ void Position::getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned
// Name: getComputersChoice()
// Desc: Returns the move the AI of the current player would do.
//-----------------------------------------------------------------------------
void Position::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo)
void Mill::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo)
{
fieldStruct theField;
*pushFrom = field.size;
@ -379,7 +380,7 @@ void Position::getComputersChoice(unsigned int *pushFrom, unsigned int *pushTo)
// Name: isNormalMovePossible()
// Desc: 'Normal' in this context means, by moving the stone along a connection without jumping.
//-----------------------------------------------------------------------------
bool Position::isNormalMovePossible(unsigned int from, unsigned int to, Player *player)
bool Mill::isNormalMovePossible(unsigned int from, unsigned int to, Player *player)
{
// locals
unsigned int movingDirection, i;
@ -419,7 +420,7 @@ bool Position::isNormalMovePossible(unsigned int from, unsigned int to, Player *
// Name: calcPossibleMoves()
// Desc: ...
//-----------------------------------------------------------------------------
void Position::calcPossibleMoves(Player *player)
void Mill::calcPossibleMoves(Player *player)
{
// locals
unsigned int i, j;
@ -456,7 +457,7 @@ void Position::calcPossibleMoves(Player *player)
// Name: setWarningAndMill()
// Desc:
//-----------------------------------------------------------------------------
void Position::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];
@ -483,7 +484,7 @@ void Position::setWarningAndMill(unsigned int stone, unsigned int firstNeighbour
// Name: updateMillsAndWarnings()
// Desc:
//-----------------------------------------------------------------------------
void Position::updateMillsAndWarnings(unsigned int newStone)
void Mill::updateMillsAndWarnings(unsigned int newStone)
{
// locals
unsigned int i;
@ -492,8 +493,10 @@ void Position::updateMillsAndWarnings(unsigned int newStone)
// 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
@ -516,10 +519,10 @@ void Position::updateMillsAndWarnings(unsigned int newStone)
}
//-----------------------------------------------------------------------------
// Name: do_move()
// Name: doMove()
// Desc:
//-----------------------------------------------------------------------------
bool Position::do_move(unsigned int pushFrom, unsigned int pushTo)
bool Mill::doMove(unsigned int pushFrom, unsigned int pushTo)
{
// avoid index override
if (movesDone >= MAX_NUM_MOVES)
@ -654,7 +657,7 @@ bool Position::do_move(unsigned int pushFrom, unsigned int pushTo)
// Name: setCurrentGameState()
// Desc: Set an arbitrary game state as the current one.
//-----------------------------------------------------------------------------
bool Position::setCurrentGameState(fieldStruct *curState)
bool Mill::setCurrentGameState(fieldStruct *curState)
{
curState->copyBoard(&field);
@ -663,8 +666,10 @@ bool Position::setCurrentGameState(fieldStruct *curState)
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;
@ -675,7 +680,7 @@ bool Position::setCurrentGameState(fieldStruct *curState)
// Name: compareWithField()
// Desc: Compares the current 'board' variable with the passed one. 'stoneMoveAble[]' is ignored.
//-----------------------------------------------------------------------------
bool Position::compareWithField(fieldStruct *compareField)
bool Mill::compareWithField(fieldStruct *compareField)
{
unsigned int i, j;
bool ret = true;
@ -684,6 +689,7 @@ bool Position::compareWithField(fieldStruct *compareField)
cout << "error - curPlayer differs!" << endl;
ret = false;
}
if (!comparePlayers(field.oppPlayer, compareField->oppPlayer)) {
cout << "error - oppPlayer differs!" << endl;
ret = false;
@ -693,37 +699,41 @@ bool Position::compareWithField(fieldStruct *compareField)
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++) {
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++) {
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;
@ -738,7 +748,7 @@ bool Position::compareWithField(fieldStruct *compareField)
// Name: comparePlayers()
// Desc: Compares the two passed players and returns false if they differ.
//-----------------------------------------------------------------------------
bool Position::comparePlayers(Player *playerA, Player *playerB)
bool Mill::comparePlayers(Player *playerA, Player *playerB)
{
// unsigned int i;
bool ret = true;
@ -747,18 +757,22 @@ bool Position::comparePlayers(Player *playerA, Player *playerB)
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;
@ -775,7 +789,7 @@ bool Position::comparePlayers(Player *playerA, Player *playerB)
// Desc: Calls the printBoard() function of the current board.
// Prints the current game state on the screen.
//-----------------------------------------------------------------------------
void Position::printBoard()
void Mill::printBoard()
{
field.printBoard();
}
@ -784,7 +798,7 @@ void Position::printBoard()
// Name: undo_move()
// Desc: Sets the initial board as the current one and apply all (minus one) moves from the move history.
//-----------------------------------------------------------------------------
void Position::undo_move(void)
void Mill::undo_move(void)
{
// locals
unsigned int *moveLogFrom_bak = new unsigned int[movesDone];
@ -808,7 +822,7 @@ void Position::undo_move(void)
// and play again
for (i = 0; i < movesDone_bak - 1; i++) {
do_move(moveLogFrom_bak[i], moveLogTo_bak[i]);
doMove(moveLogFrom_bak[i], moveLogTo_bak[i]);
}
}
@ -821,7 +835,7 @@ void Position::undo_move(void)
// Name: calcNumberOfRestingStones()
// Desc:
//-----------------------------------------------------------------------------
void Position::calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting)
void Mill::calcNumberOfRestingStones(int &numWhiteStonesResting, int &numBlackStonesResting)
{
if (getCurrentPlayer() == fieldStruct::playerTwo) {
numWhiteStonesResting = fieldStruct::numStonesPerPlayer - field.curPlayer->numStonesMissing - field.curPlayer->numStones;

View File

@ -1,13 +1,13 @@
/*********************************************************************\
Position.h
Mill.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
#define MUEHLE_H
#ifndef MILL_H
#define MILL_H
#include <iostream>
#include <cstdio>
@ -42,7 +42,7 @@ using namespace std;
/*** Klassen *********************************************************/
class Position
class Mill
{
private:
// Variables
@ -64,21 +64,21 @@ private:
public:
// Constructor / destructor
Position();
~Position();
Mill();
~Mill();
// 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);
bool doMove(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 putPiece(unsigned int pos, int player);
bool settingPhaseHasFinished();
void getChoiceOfSpecialAI(MillAI *AI, unsigned int *pushFrom, unsigned int *pushTo);
void setUpCalcPossibleMoves(Player *player);
@ -90,46 +90,57 @@ public:
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;

View File

@ -123,6 +123,7 @@ void Player::copyPlayer(Player *destination)
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];
}

View File

@ -94,6 +94,7 @@ public:
{
dummyField.createBoard();
};
~MillAI()
{
dummyField.deleteBoard();

View File

@ -116,7 +116,6 @@ unsigned int *MiniMaxAI::getPossSettingPhase(unsigned int *numPossibilities, voi
// possibilities with cut off
for ((*numPossibilities) = 0, i = 0; i < field->size; i++) {
// move possible ?
if (field->board[i] == field->squareIsFree) {
@ -144,7 +143,6 @@ unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void
// 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++) {
@ -165,7 +163,6 @@ unsigned int *MiniMaxAI::getPossNormalMove(unsigned int *numPossibilities, void
}
}
} else {
for ((*numPossibilities) = 0, from = 0; from < field->size; from++) {
for (to = 0; to < field->size; to++) {
@ -387,12 +384,14 @@ inline void MiniMaxAI::updateWarning(unsigned int firstStone, unsigned int secon
// 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;
}
@ -413,14 +412,12 @@ inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwne
// neighbor must exist
if (neighbor < field->size) {
// 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 (stoneRemoved)
stoneOwner->numPossibleMoves--;
else
@ -428,13 +425,11 @@ inline void MiniMaxAI::updatePossibleMoves(unsigned int stone, Player *stoneOwne
// 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->oppPlayer->numPossibleMoves++;
else
@ -588,6 +583,7 @@ void MiniMaxAI::move(unsigned int threadNo, unsigned int idPossibility, bool opp
// 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;

View File

@ -44,6 +44,7 @@ MiniMax::MiniMax()
numWriteSkvOperations = 0;
numReadPlyOperations = 0;
numWritePlyOperations = 0;
if (MEASURE_ONLY_IO) {
readSkvInterval.QuadPart = 0;
writeSkvInterval.QuadPart = 0;
@ -90,6 +91,7 @@ bool MiniMax::falseOrStop()
{
if (stopOnCriticalError)
WaitForSingleObject(GetCurrentProcess(), INFINITE);
return false;
}
@ -145,7 +147,6 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
// when database not completed then do it
if (hFileShortKnotValues != nullptr && skvfHeader.completed == false) {
// reserve memory
lastCalculatedLayer.clear();
depthOfFullTree = maxDepthOfTree;
@ -186,8 +187,8 @@ void MiniMax::calculateDatabase(unsigned int maxDepthOfTree, bool onlyPrepareLay
// don't save layer and header when only preparing layers or when
if (onlyPrepareLayer)
return;
if (!abortCalculation) {
if (!abortCalculation) {
// calc layer statistics
calcLayerStatistics("statistics.txt");
@ -223,7 +224,6 @@ 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
layersToCalculate.push_back(layerNumber);
if (layerNumber != layerStats[layerNumber].partnerLayer)

View File

@ -292,25 +292,30 @@ public:
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)
@ -321,29 +326,34 @@ public:
{
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)
@ -356,6 +366,7 @@ public:
while (true)
;
};
virtual bool setSituation(unsigned int threadNo, unsigned int layerNum, unsigned int stateNumber)
{
while (true)
@ -386,11 +397,13 @@ public:
;
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)
@ -413,6 +426,7 @@ public:
while (true)
;
};
virtual void wrapUpDatabaseCalculation(bool calculationAborted)
{
while (true)
@ -481,6 +495,7 @@ private:
AlphaBetaDefaultThreadVars()
{
};
AlphaBetaDefaultThreadVars(MiniMax *pMiniMax, AlphaBetaGlobalVars *alphaBetaVars, unsigned int layerNumber)
{
this->statesProcessed = 0;
@ -491,6 +506,7 @@ private:
this->statsValueCounter[curStateValue] = 0;
}
};
void reduceDefault()
{
pMiniMax->numStatesProcessed += this->statesProcessed;
@ -508,15 +524,18 @@ private:
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();
@ -532,19 +551,23 @@ private:
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;
@ -592,6 +615,7 @@ private:
RetroAnalysisDefaultThreadVars()
{
};
RetroAnalysisDefaultThreadVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber)
{
this->statesProcessed = 0;
@ -602,6 +626,7 @@ private:
this->statsValueCounter[curStateValue] = 0;
}
};
void reduceDefault()
{
pMiniMax->numStatesProcessed += this->statesProcessed;
@ -619,15 +644,18 @@ private:
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();
@ -641,13 +669,16 @@ private:
AddNumSuccedorsVars()
{
};
AddNumSuccedorsVars(MiniMax *pMiniMax, retroAnalysisGlobalVars *retroVars, unsigned int layerNumber) : RetroAnalysisDefaultThreadVars(pMiniMax, retroVars, layerNumber)
{
};
void initializeElement(AddNumSuccedorsVars &master)
{
*this = master;
};
void reduce()
{
reduceDefault();

View File

@ -86,52 +86,66 @@ protected:
{
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)
{
};

View File

@ -22,9 +22,11 @@ public:
virtual void setAlignment(wildWeasel::alignment &newAlignment)
{
};
virtual void setVisibility(bool visible)
{
};
virtual void setState(unsigned int curShowedLayer, MiniMax::StateNumberVarType curShowedState)
{
};

View File

@ -106,6 +106,7 @@ bool MiniMax::initAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
// 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;
@ -216,6 +217,7 @@ DWORD MiniMax::initAlphaBetaThreadProc(void *pParameter, int index)
return m->falseOrStop();
}
}
iabVars->statsValueCounter[curStateValue]++;
return TM_RETURN_VALUE_OK;
@ -251,6 +253,7 @@ bool MiniMax::runAlphaBeta(AlphaBetaGlobalVars &alphaBetaVars)
case TM_RETURN_VALUE_UNEXPECTED_ERROR:
return falseOrStop();
}
threadManager.setNumThreads(4);
// reduce and delete thread specific data
@ -292,6 +295,7 @@ DWORD MiniMax::runAlphaBetaThreadProc(void *pParameter, int index)
// 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;
@ -354,7 +358,6 @@ void MiniMax::letTheTreeGrow(Knot *knot, RunAlphaBetaVars *rabVars, unsigned int
// 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);
@ -370,7 +373,6 @@ 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);
@ -407,7 +409,6 @@ bool MiniMax::alphaBetaTryDataBase(Knot *knot, RunAlphaBetaVars *rabVars, unsign
// 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);
@ -453,7 +454,6 @@ void MiniMax::alphaBetaTryPossibilites(Knot *knot, RunAlphaBetaVars *rabVars, un
unsigned int curPoss;
for (curPoss = 0; curPoss < knot->numPossibilities; curPoss++) {
// output
if (tilLevel == depthOfFullTree && !calcDatabase) {
printMoveInformation(rabVars->curThreadNo, idPossibility[curPoss], pPossibilities);
@ -491,6 +491,7 @@ void MiniMax::alphaBetaTryPossibilites(Knot *knot, RunAlphaBetaVars *rabVars, un
// don't use alpha beta if using database
if (hFileShortKnotValues != nullptr && calcDatabase)
continue;
if (hFileShortKnotValues != nullptr && tilLevel + 1 >= depthOfFullTree)
continue;
@ -581,7 +582,6 @@ void MiniMax::alphaBetaCalcPlyInfo(Knot *knot)
// when current knot is a won state
if (shortKnotValue == SKV_VALUE_GAME_WON) {
for (i = 0; i < knot->numPossibilities; i++) {
// invert knot value if necessary
@ -600,9 +600,7 @@ void MiniMax::alphaBetaCalcPlyInfo(Knot *knot)
// current state is a lost state
} else {
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;
@ -638,7 +636,6 @@ void MiniMax::alphaBetaChooseBestMove(Knot *knot, RunAlphaBetaVars *rabVars, uns
// 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++) {

View File

@ -318,7 +318,6 @@ void MiniMax::openPlyInfoFile(const char *directory)
// invalid file ?
if (dwBytesRead != sizeof(plyInfoHeader) || plyInfoHeader.headerCode != PLYINFO_HEADER_CODE) {
// create default header
plyInfoHeader.plyInfoCompleted = false;
plyInfoHeader.numLayers = getNumberOfLayers();
@ -363,6 +362,7 @@ 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;
@ -472,6 +472,7 @@ void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int s
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];
@ -488,6 +489,7 @@ void MiniMax::readKnotValueFromDatabase(unsigned int layerNumber, unsigned int s
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);
}
@ -533,7 +535,6 @@ void MiniMax::readPlyInfoFromDatabase(unsigned int layerNumber, unsigned int sta
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);
@ -595,7 +596,6 @@ void MiniMax::saveKnotValueInDatabase(unsigned int layerNumber, unsigned int sta
// 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
@ -659,20 +659,23 @@ void MiniMax::savePlyInfoInDatabase(unsigned int layerNumber, unsigned int state
// 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);
}

View File

@ -39,6 +39,7 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
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;
@ -51,6 +52,7 @@ bool MiniMax::calcKnotValuesByRetroAnalysis(vector<unsigned int> &layersToCalcul
retroVars.totalNumKnots += layerStats[layerStats[layersToCalculate[curLayer]].succLayers[curSubLayer]].knotsInLayer;
}
}
retroVars.layerInitialized.assign(skvfHeader.numLayers, false);
// output & filenames
@ -97,6 +99,7 @@ freeMem:
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);
@ -104,8 +107,10 @@ freeMem:
}
SAFE_DELETE_ARRAY(retroVars.countArrays[curLayer]);
}
if (!abortCalculation)
PRINT(2, this, " Bytes in memory: " << memoryUsed2);
return !abortCalculation;
}
@ -125,7 +130,6 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars)
// 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;
@ -178,6 +182,7 @@ bool MiniMax::initRetroAnalysis(retroAnalysisGlobalVars &retroVars)
initAlreadyDone = false;
initArray->flushBuffers();
SAFE_DELETE(initArray);
if (numStatesProcessed < layerStats[layerNumber].knotsInLayer)
return falseOrStop();
@ -225,7 +230,6 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index)
// initialization not done
} else {
// set current selected situation
if (!m->setSituation(iraVars->curThreadNo, curState.layerNumber, curState.stateNumber)) {
curStateValue = SKV_VALUE_INVALID;
@ -237,13 +241,11 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index)
// save init value
if (curStateValue != SKV_VALUE_INVALID) {
// 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) {
// ply info
m->savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, 0);
@ -260,6 +262,7 @@ DWORD MiniMax::initRetroAnalysisThreadProc(void *pParameter, int index)
return m->falseOrStop();
}
}
iraVars->statsValueCounter[curStateValue]++;
return TM_RETURN_VALUE_OK;
@ -287,6 +290,7 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
// 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);
@ -294,6 +298,7 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
// 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();
@ -344,6 +349,7 @@ bool MiniMax::prepareCountArrays(retroAnalysisGlobalVars &retroVars)
if (dwWritten != numKnotsInCurLayer * sizeof(CountArrayVarType))
return falseOrStop();
}
PRINT(2, this, " Count array saved to file: " << ssCountArrayFilePath.str());
}
@ -496,7 +502,6 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
// iteration
for (curPred = 0; curPred < amountOfPred; curPred++) {
// current predecessor
predState.layerNumber = ansVars->predVars[curPred].predLayerNumbers;
predState.stateNumber = ansVars->predVars[curPred].predStateNumbers;
@ -506,6 +511,7 @@ DWORD MiniMax::addNumSuccedorsThreadProc(void *pParameter, int index)
if (ansVars->retroVars->layersToCalculate[curLayerId] == predState.layerNumber)
break;
}
if (curLayerId == numLayersToCalculate)
continue;
@ -577,6 +583,7 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars)
// 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);
@ -586,6 +593,7 @@ bool MiniMax::performRetroAnalysis(retroAnalysisGlobalVars &retroVars)
savePlyInfoInDatabase(curState.layerNumber, curState.stateNumber, PLYINFO_VALUE_INVALID);
}
}
PRINT(1, this, " *** Iteration finished! ***");
// every thing ok
@ -624,7 +632,6 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
// 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++) {
@ -633,7 +640,6 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
}
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");
@ -671,7 +677,6 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
// iteration
for (curPred = 0; curPred < amountOfPred; curPred++) {
// current predecessor
predState.layerNumber = predVars[curPred].predLayerNumbers;
predState.stateNumber = predVars[curPred].predStateNumbers;
@ -689,7 +694,6 @@ DWORD MiniMax::performRetroAnalysisThreadProc(void *pParameter)
// 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);
@ -780,5 +784,6 @@ bool MiniMax::addStateToProcessQueue(retroAnalysisGlobalVars &retroVars, RetroAn
// everything was fine
threadVars.numStatesToProcess++;
return true;
}

View File

@ -141,7 +141,6 @@ void MiniMax::showLayerStats(unsigned int layerNumber)
// 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]++;
@ -220,7 +219,6 @@ bool MiniMax::calcLayerStatistics(char *statisticsFileName)
// only calc stats of completed layers
if (layerStats[curState.layerNumber].layerIsCompletedAndInFile) {
for (curState.stateNumber = 0; curState.stateNumber < layerStats[curState.layerNumber].knotsInLayer; curState.stateNumber++) {
// get state value
@ -321,6 +319,7 @@ void MiniMax::ArrayInfoContainer::addArray(unsigned int layerNumber, unsigned in
{
// create new info object and add to list
EnterCriticalSection(&c->csOsPrint);
ArrayInfo ais;
ais.belongsToLayer = layerNumber;
ais.compressedSizeInBytes = compressedSize;
@ -342,6 +341,7 @@ void MiniMax::ArrayInfoContainer::addArray(unsigned int layerNumber, unsigned in
if (c->userPrintFunc != nullptr) {
c->userPrintFunc(c->pDataForUserPrintFunc);
}
LeaveCriticalSection(&c->csOsPrint);
}
@ -378,6 +378,7 @@ void MiniMax::ArrayInfoContainer::removeArray(unsigned int layerNumber, unsigned
if (c->userPrintFunc != nullptr) {
c->userPrintFunc(c->pDataForUserPrintFunc);
}
LeaveCriticalSection(&c->csOsPrint);
}
@ -395,6 +396,7 @@ void MiniMax::ArrayInfoContainer::updateArray(unsigned int layerNumber, unsigned
// notify cahnge
EnterCriticalSection(&c->csOsPrint);
ArrayInfoChange aic;
aic.arrayInfo = &(*itr);
aic.itemIndex = (unsigned int)std::distance(listArrays.begin(), itr);
@ -405,6 +407,7 @@ void MiniMax::ArrayInfoContainer::updateArray(unsigned int layerNumber, unsigned
c->userPrintFunc(c->pDataForUserPrintFunc);
}
itr->updateCounter = 0;
LeaveCriticalSection(&c->csOsPrint);
}
}

View File

@ -35,6 +35,7 @@ bool MiniMax::testLayer(unsigned int layerNumber)
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;
@ -161,7 +162,6 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
goto errorInDatabase;
}
} else {
// check each possible move
for (i = 0; i < numPossibilities; i++) {
@ -194,7 +194,6 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
// 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) {
@ -231,7 +230,6 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
break;
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; }
@ -263,7 +261,6 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
break;
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; }
@ -306,6 +303,7 @@ DWORD MiniMax::testLayerThreadProc(void *pParameter, int index)
break;
}
}
return TM_RETURN_VALUE_OK;
errorInDatabase:
@ -360,6 +358,7 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber)
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;
@ -372,6 +371,7 @@ bool MiniMax::testSetSituationAndGetPoss(unsigned int layerNumber)
// 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:
@ -430,6 +430,7 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int 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");
@ -481,6 +482,7 @@ DWORD MiniMax::testSetSituationThreadProc(void *pParameter, int index)
m->setSituation(tlVars->curThreadNo, curState.layerNumber, curState.stateNumber);
}
}
return TM_RETURN_VALUE_OK;
//errorInDatabase:
@ -525,7 +527,6 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
skvfHeader.completed = false;
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");
@ -549,7 +550,6 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
// save value for all symmetric states
for (i = 0; i < numSymmetricStates; i++) {
readKnotValueFromDatabase(layerNumber, symStateNumbers[i], shortValueOfSymState);
readPlyInfoFromDatabase(layerNumber, symStateNumbers[i], numPliesTillSymState);
@ -571,6 +571,7 @@ bool MiniMax::testIfSymStatesHaveSameValue(unsigned int layerNumber)
// layer is ok
PRINT(0, this, "TEST PASSED !");
return true;
errorInDatabase:
@ -578,5 +579,6 @@ errorInDatabase:
// layer is not ok
if (layerNumber)
PRINT(0, this, "DATABASE ERROR IN LAYER " << layerNumber << " AND STATE " << stateNumber);
return falseOrStop();
}

View File

@ -154,7 +154,7 @@
<ClInclude Include="miniMaxWin.h" />
<ClInclude Include="miniMax_retroAnalysis.h" />
<ClInclude Include="miniMaxAI.h" />
<ClInclude Include="position.h" />
<ClInclude Include="mill.h" />
<ClInclude Include="millAI.h" />
<ClInclude Include="perfectAI.h" />
<ClInclude Include="randomAI.h" />
@ -172,7 +172,7 @@
<ClCompile Include="miniMax_statistics.cpp" />
<ClCompile Include="miniMax_test.cpp" />
<ClCompile Include="minMaxAI.cpp" />
<ClCompile Include="position.cpp" />
<ClCompile Include="mill.cpp" />
<ClCompile Include="millAI.cpp" />
<ClCompile Include="perfectAI.cpp" />
<ClCompile Include="randomAI.cpp" />

View File

@ -51,7 +51,7 @@
<ClInclude Include="config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="position.h">
<ClInclude Include="mill.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@ -98,10 +98,10 @@
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="position.cpp">
<ClCompile Include="minMaxAI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="minMaxAI.cpp">
<ClCompile Include="mill.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -8,149 +8,166 @@
#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 };
@ -187,6 +204,7 @@ PerfectAI::PerfectAI(const char *directory)
//
threadVars = new ThreadVars[getNumThreads()];
for (unsigned int curThread = 0; curThread < getNumThreads(); curThread++) {
threadVars[curThread].parent = this;
threadVars[curThread].field = &dummyField;
@ -199,13 +217,13 @@ PerfectAI::PerfectAI(const char *directory)
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) {
// 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);
@ -308,7 +326,6 @@ PerfectAI::PerfectAI(const char *directory)
// 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++) {
@ -353,7 +370,6 @@ PerfectAI::PerfectAI(const char *directory)
indexAB[stateAB] = NOT_INDEXED;
for (stateAB = 0; stateAB < MAX_ANZ_STELLUNGEN_A * MAX_ANZ_STELLUNGEN_B; stateAB++) {
// new state ?
if (indexAB[stateAB] == NOT_INDEXED) {
@ -399,7 +415,8 @@ PerfectAI::PerfectAI(const char *directory)
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]];
originalStateCD_tmp[a][b] =
new unsigned int[mOverN[numSquaresGroupC + numSquaresGroupD][a] * mOverN[numSquaresGroupC + numSquaresGroupD - a][b]];
anzahlStellungenCD[a][b] = 0;
}
}
@ -408,7 +425,6 @@ PerfectAI::PerfectAI(const char *directory)
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++) {
// new state ?
if (indexCD[stateCD] == NOT_INDEXED) {
@ -2289,6 +2305,7 @@ void PerfectAI::getPredecessors(unsigned int threadNo, unsigned int *amountOfPre
}
}
}
} else if (!tv->gameHasFinished) {
// test each destination
@ -2371,7 +2388,6 @@ void PerfectAI::getPredecessors(unsigned int threadNo, unsigned int *amountOfPre
// 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;
@ -2456,12 +2472,14 @@ bool PerfectAI::checkMoveAndSetSituation()
// 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;
@ -2634,13 +2652,17 @@ bool PerfectAI::checkGetPredThanGetPoss()
// 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;
@ -2648,6 +2670,7 @@ bool PerfectAI::checkGetPredThanGetPoss()
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;
@ -2659,10 +2682,14 @@ bool PerfectAI::checkGetPredThanGetPoss()
// 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;
@ -2676,7 +2703,6 @@ bool PerfectAI::checkGetPredThanGetPoss()
// go to each successor state
for (i = 0; i < numPossibilities; i++) {
// move
move(threadNo, idPossibility[i], isOpponentLevel, &pBackup, pPossibilities);
@ -2693,22 +2719,28 @@ bool PerfectAI::checkGetPredThanGetPoss()
// error?
if (i == numPossibilities) {
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;
@ -2716,6 +2748,7 @@ bool PerfectAI::checkGetPredThanGetPoss()
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;
@ -2726,15 +2759,22 @@ bool PerfectAI::checkGetPredThanGetPoss()
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);

View File

@ -186,6 +186,7 @@ protected:
void calcPossibleMoves(Player *player);
void storePredecessor(unsigned int numberOfMillsCurrentPlayer, unsigned int numberOfMillsOpponentPlayer, unsigned int *amountOfPred, RetroAnalysisPredVars *predVars);
};
ThreadVars *threadVars;
// database functions

View File

@ -39,7 +39,6 @@ void RandomAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
// must stone be removed ?
if (theField->stoneMustBeRemoved) {
// search a stone from the enemy
do {
from = rand() % theField->size;
@ -48,7 +47,6 @@ void RandomAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
// still in setting phase ?
} else if (theField->settingPhase) {
// search a free square
do {
from = theField->size;
@ -57,7 +55,6 @@ void RandomAI::play(fieldStruct *theField, unsigned int *pushFrom, unsigned int
// try to push randomly
} else {
do {
// search an own stone
do {

View File

@ -58,10 +58,12 @@ MyString::~MyString()
delete[] strA;
strA = nullptr;
}
if (strW != nullptr) {
delete[] strW;
strW = nullptr;
}
strW = nullptr;
strA = nullptr;
length = 0;
@ -99,8 +101,10 @@ MyString &MyString::assign(const char *cStr)
if (reserved < newReserved)
this->~MyString();
if (strA == nullptr)
strA = new char[newReserved];
if (strW == nullptr)
strW = new WCHAR[newReserved];
@ -126,8 +130,10 @@ MyString &MyString::assign(const WCHAR *cStr)
if (reserved < newReserved)
this->~MyString();
if (strA == nullptr)
strA = new char[newReserved];
if (strW == nullptr)
strW = new WCHAR[newReserved];
@ -179,7 +185,6 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
// read each value
do {
// read from buffer if necessary
if (curBufferPos >= bufferSize - maxValueLengthInBytes) {
memcpy(&buffer[0], &buffer[curBufferPos], bufferSize - curBufferPos);
@ -352,9 +357,11 @@ bool readAsciiData(HANDLE hFile, double *pData, unsigned int numValues, unsigned
if (decimalPos) {
(*pData) += fractionalValue * fractionalFactor[decimalPos];
}
if (valIsNegativ) {
(*pData) *= -1;
}
if (exponent) {
(*pData) *= pow(10, expIsNegativ ? -1 * exponentialValue : 1);
}

View File

@ -58,9 +58,11 @@ ThreadManager::~ThreadManager()
if (hBarrier != nullptr)
delete[] hBarrier;
hBarrier = nullptr;
if (hThread != nullptr)
delete[] hThread;
hThread = nullptr;
if (threadId != nullptr)
delete[] threadId;
threadId = nullptr;
@ -127,18 +129,24 @@ 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;
}
@ -149,7 +157,6 @@ bool ThreadManager::setNumThreads(unsigned int newNumThreads)
void ThreadManager::pauseExecution()
{
for (unsigned int curThread = 0; curThread < numThreads; curThread++) {
// unsuspend all threads
if (!executionPaused) {
SuspendThread(hThread[curThread]);
@ -158,6 +165,7 @@ void ThreadManager::pauseExecution()
ResumeThread(hThread[curThread]);
}
}
executionPaused = (!executionPaused);
}
@ -170,6 +178,7 @@ void ThreadManager::cancelExecution()
{
termineAllThreads = true;
executionCancelled = true;
if (executionPaused) {
pauseExecution();
}
@ -208,6 +217,7 @@ unsigned int ThreadManager::getThreadNumber()
return curThreadNo;
}
}
return 0;
}
@ -284,12 +294,16 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
// 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;
@ -305,7 +319,6 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
// 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;
@ -335,14 +348,18 @@ unsigned int ThreadManager::executeParallelLoop(DWORD threadProc(void *pParamete
// 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);
}

View File

@ -78,9 +78,11 @@ public:
virtual void initializeElement()
{
};
virtual void destroyElement()
{
};
virtual void reduce()
{
};