/* -*- Mode: C -*- */ #define debugprint #include #include #include #include #include #include #include #include #include "playerlib.h" static int send_move(int row, int col) { FILE *f = fdopen(dup(CHILD_OUT_FD), "w"); fprintf(f, "%u,%u", row, col); fclose(f); return 0; } //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 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); // auto futureField = new cell[fieldSize][fieldSize](); // memcpy(futureField, field, fieldMemSize); // futureField[(moves->list[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc; // movesList *futureMoves = new movesList(); // findMoves(futureField, futureMoves, enemyc); // buildTree(&(currentNode->childMove[i]), futureField, futureMoves, depth-1, getEnemyChar(enemyc)); // delete [] futureMoves; // delete [] futureField; // } // return 1; //} move maxEvalMove(std::vector *curMoves) { evalMove maxM; maxM.evaluation = -99; for(size_t i = 0; i < curMoves->size(); ++i) { if(curMoves->at(i).evaluation > maxM.evaluation) { 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 (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); //} move nFindBestMove(cell (*field)[fieldSize], movesList *moves, char enemyc) { std::vector curMoves; printf("NumOwnMoves: %d\n", moves->movesNumber); for(size_t i=0; i < moves->movesNumber; ++i) { #ifdef debugprint printf("EnemyMove %d ", i); #endif size_t fieldMemSize = fieldSize*fieldSize*sizeof(cell); auto futureField = new cell[fieldSize][fieldSize](); memcpy(futureField, field, fieldMemSize); futureField[(moves->list[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc; movesList *futureMoves = new movesList(); findMoves(futureField, futureMoves, enemyc); evalMove m; m.m = moves->list[i]; //gut: Eckzüge. Schlecht: hohe Mobilität des Gegners, Züge auf Felder direkt vor der Ecke m.evaluation = 5*isCornerField(m.m) - futureMoves->movesNumber - 2*(!endgame)*isCOrXField(m.m); #ifdef debugprint printf("eval: %d, move: %d, %d\n", m.evaluation, m.m.turnRow, m.m.turnCol); #endif curMoves.push_back(m); #ifdef debugprint printf("m: (%d, %d) hat %d\n", m.m.turnRow, m.m.turnCol, m.evaluation); #endif delete [] futureMoves; delete [] futureField; } return maxEvalMove(&curMoves); } int main(void) { int done = 0; srandom(time(NULL)); char enemyc=0, ownc=0; while (!done) { int turn_row = 0; int turn_col = 0; /* BEGIN PLAYER-SPECIFIC CODE */ // 1. Read state char state_buffer[128]; ssize_t bytes = read(CHILD_IN_FD, state_buffer, sizeof(state_buffer)); if (bytes != 65) // invalid number of chars abort(); // state_buffer enthält jetzt 65 Zeichen ('.' oder 'X' oder 'O'): // * Das ERSTE Zeichen gibt an, welcher Spieler an der Reihe ist. // * Die weiteren 64 Zeichen definieren die Belegung des Feldes. // * Die Belegung wird reihenweise gegeben, d.h. die Zeichen // 1 bis 8 definieren die erste Zeile des Feldes, Zeichen 9 bis 17 // geben die zweite Zeile usw. // * X und O stehen hierbei für die jeweiligen Spieler. Leere Felder // sind durch einen Punkt (.) gekennzeichnet. // 2. TODO: Strategie hier einfügen. Resultat in turn_row und turn_col speichern. //number of stones of X/O unsigned int numX=0, numO=0; //TODO: make it a property of field struct ownc = state_buffer[0]; if(!enemyc) { enemyc = getEnemyChar(ownc); } auto field = new cell[fieldSize][fieldSize](); readStateBuffer(state_buffer, field, &numX, &numO); //stateBuffer ist Pointer auf char, field ist Pointer auf struct cell[] movesList *moves = new movesList(); findMoves(field, moves, enemyc); // 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]); // } if(!(moves->movesNumber)) { turn_row=0; turn_col=0; #ifdef debugprint printf("Nope\n"); #endif } else { move finalMove; if(moves->movesNumber == 1) finalMove = moves->list[0]; else { 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, 1, getEnemyChar(enemyc)); finalMove = nFindBestMove(field, moves, getEnemyChar(enemyc)); } turn_row=finalMove.turnRow; turn_col=finalMove.turnCol; #ifdef debugprint printf("Getätigter Zug: %d,%d\n", turn_row, turn_col); #endif } // 3. Return result send_move(turn_row, turn_col); //free(numOfEnemyMoves); delete [] field; delete [] moves; /* END PLAYER-SPECIFIC CODE */ } return 0; } /* EOF */