From 4dd39b5e79d0fa769423cc34d449f67142da101f Mon Sep 17 00:00:00 2001 From: Trolli Schmittlauch Date: Fri, 13 Mar 2015 04:06:26 +0100 Subject: [PATCH] theorethisch, aber npraktisch doch nicht funktionierender MiniMax Algorithmus --- players/my-player.cc | 154 ++++++++++++++++++++++++++++++------------- players/playerlib.cc | 2 + players/playerlib.h | 13 ++++ 3 files changed, 125 insertions(+), 44 deletions(-) diff --git a/players/my-player.cc b/players/my-player.cc index b2caf91..d40e8e6 100644 --- a/players/my-player.cc +++ b/players/my-player.cc @@ -7,12 +7,13 @@ #include #include #include +#include #include #include "playerlib.h" - static int +static int send_move(int row, int col) { FILE *f = fdopen(dup(CHILD_OUT_FD), "w"); @@ -21,44 +22,104 @@ send_move(int row, int col) return 0; } -unsigned int* -numNextMoves(cell (*field)[fieldSize], movesList *moves) { +int +buildTree(gameTree *currentNode, cell (*field)[fieldSize], movesList *moves, int depth, char enemyc) { + if (depth == 0 || moves->movesNumber == 0) + return 0; + currentNode->numChildMoves = moves->movesNumber; + currentNode->childMove = new gameTree[maxMoves](); //switch stone char - char tmpown = ownc, tmpenemy = enemyc; - char enemyc = getEnemyChar(tmpenemy); - char ownc = getEnemyChar(tmpown); -#ifdef debugprint - printf("Own: %c Enemy: %c\n", ownc, enemyc); -#endif - unsigned int *numberOfEnemyMoves= new unsigned int[maxMoves](); - for (size_t moveNum=0; moveNum < moves->movesNumber; ++moveNum) + ownc = getEnemyChar(enemyc); + +//#ifdef debugprint +// printf("Depth %d: enemy: %c\n", depth, enemyc); +//#endif + for(size_t i=0; imovesNumber; ++i) { + currentNode->childMove[i].nodeMove = moves->list[i]; size_t fieldMemSize = fieldSize*fieldSize*sizeof(cell); - //cell (*futureField)[fieldSize] = (cell (*)[fieldSize]) malloc(fieldMemSize); auto futureField = new cell[fieldSize][fieldSize](); memcpy(futureField, field, fieldMemSize); - futureField[(moves->list[moveNum].turnRow-1)][(moves->list[moveNum].turnCol-1)].content=enemyc; - printf("--------------------\nfutureField\n"); -#ifdef debugprint - for(size_t n=0;nlist[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc; movesList *futureMoves = new movesList(); findMoves(futureField, futureMoves); - numberOfEnemyMoves[moveNum] = futureMoves->movesNumber; + buildTree(&(currentNode->childMove[i]), futureField, futureMoves, depth-1, getEnemyChar(enemyc)); delete [] futureMoves; delete [] futureField; - //free(futureField); } - return numberOfEnemyMoves; + return 1; } +move +maxEvalMove(std::vector *curMoves) { + evalMove maxM; + maxM.evaluation = -9; +#ifdef debugprint + printf("Foo\n"); +#endif + for(size_t i = 0; i < curMoves->size(); ++i) + { +#ifdef debugprint + printf("bar %d %d\n", maxM.evaluation, curMoves->at(i).evaluation); +#endif + if(curMoves->at(i).evaluation > maxM.evaluation) + { +#ifdef debugprint + printf("baz\n"); +#endif + maxM.evaluation = curMoves->at(i).evaluation; + maxM.m = curMoves->at(i).m; + } + } + return maxM.m; +} + +int +maxInt(std::vector *evaluations) { + int maxE = -10; + for(size_t i = 0; isize(); ++i) + { + if(evaluations->at(i) > maxE) + { + maxE = evaluations->at(i); + } + } + return maxE; +} + +//MiniMax Algorithmus +int +eval(gameTree *currentNode, int depth) { + if (depth == 0 || !currentNode->numChildMoves) + { + //gut: hohe Mobilität, Eckzüge. Schlecht: Züge auf Felder direkt vor der Ecke + return ((-1)+currentNode->numChildMoves + 5*isCornerField(currentNode->nodeMove) - 2*isCOrXField(currentNode->nodeMove)); + } + + std::vector curEvals; + for(size_t i = 0; i < currentNode->numChildMoves; ++i) + { + int curEval = -1 * eval(&(currentNode->childMove[i]), depth-1); + curEvals.push_back(curEval); + } + return maxInt(&curEvals); +} + +move +findBestMove(gameTree *currentNode, int depth) { + std::vector curMoves; + for(size_t i = 0; i < currentNode->numChildMoves; ++i) + { + evalMove m; + m.evaluation = -1 * eval(&(currentNode->childMove[i]), depth-1); + m.m = currentNode->childMove[i].nodeMove; +#ifdef debugprint + printf("findBest %d: %d, %d\n", m.evaluation, m.m.turnRow, m.m.turnCol); +#endif + curMoves.push_back(m); + } + return maxEvalMove(&curMoves); +} int main(void) @@ -103,39 +164,44 @@ int main(void) findMoves(field, moves); - unsigned int *numOfEnemyMoves = numNextMoves(field, moves); + // unsigned int *numOfEnemyMoves = numNextMoves(field, moves); - for(size_t i=0; imovesNumber; ++i) - { - printf("Moves %d %d -> %d enemy moves\n", moves->list[i].turnRow, moves->list[i].turnCol, numOfEnemyMoves[i]); - } + // for(size_t i=0; imovesNumber; ++i) + // { + // printf("Moves %d %d -> %d enemy moves\n", moves->list[i].turnRow, moves->list[i].turnCol, numOfEnemyMoves[i]); + // } if(!(moves->movesNumber)) { turn_row=0; turn_col=0; +#ifdef debugprint + printf("Nope\n"); +#endif } else { - int r = rand() % moves->movesNumber; - turn_row=moves->list[r].turnRow; - turn_col=moves->list[r].turnCol; + if((numX+numO)>5*fieldSize*fieldSize/6) + endgame = 1; + gameTree *treeRoot = new gameTree(); + treeRoot->nodeMove.turnRow = 0; + treeRoot->nodeMove.turnCol = 0; + buildTree(treeRoot, field, moves, 3, getEnemyChar(enemyc)); + move finalMove = findBestMove(treeRoot, 3); + + turn_row=finalMove.turnRow; + turn_col=finalMove.turnCol; +#ifdef debugprint + printf("Getätigter Zug: %d,%d\n", turn_row, turn_col); +#endif } -#ifdef debugprint - printf("numX: %d, numO: %d\n", numX, numO); - printf("%d %d\n", sizeof(field), sizeof(cell[fieldSize][fieldSize])); - move te; - te.turnRow=2; - te.turnCol=1; - printf("IsCorner? %d\n", isCOrXField(te)); -#endif - // 3. Return result send_move(turn_row, turn_col); + //free(numOfEnemyMoves); delete [] field; delete [] moves; /* END PLAYER-SPECIFIC CODE */ diff --git a/players/playerlib.cc b/players/playerlib.cc index be2407a..33f7b49 100644 --- a/players/playerlib.cc +++ b/players/playerlib.cc @@ -1,6 +1,7 @@ //#define debugprint #include #include +#include #include "playerlib.h" @@ -24,6 +25,7 @@ int findDiagonalTopRightMoves(cell (*)[fieldSize], movesList *); char enemyc = 0, ownc = 0; +unsigned int endgame=0; char getEnemyChar(char c) { diff --git a/players/playerlib.h b/players/playerlib.h index fc20d8d..f3ff553 100644 --- a/players/playerlib.h +++ b/players/playerlib.h @@ -2,6 +2,7 @@ #define PLAYERLIB_H const int fieldSize=8, maxMoves=100; // =fieldHeight=fieldWidth +extern unsigned int endgame; extern char enemyc; //initially 0, contains char of enemy's stone extern char ownc; @@ -19,6 +20,18 @@ struct movesList { move *list = new move[maxMoves](); //eigentlich maximal 8*8-4 Lösungen, aber manche doppelt? -> Reserve }; +struct gameTree{ + int evaluation; + move nodeMove; + gameTree *childMove = NULL; + unsigned int numChildMoves=0; +}; + +struct evalMove{ + int evaluation; + move m; +}; + //returns the character used for the enemy's stones extern char getEnemyChar(char); //reads the stateBuffer string into a 2d matrix