int minimax_threat(int player, luint m[4], int depth, int hash, int u, int v){ //minimax ale player musí hrat na hranu (u,v) ktera je volna // print_adjacency_matrix(m,""); timer++; luint m2[4]; int hash2; if ( NORMALIZATION_FREQUENCY > 0 && depth % NORMALIZATION_FREQUENCY == 0) hash = normalization(m,hash); int winner; if ( (winner = get_from_cache(m,hash) ) != 42){ // if ( depth % 3 == 1 && (winner = get_from_cache(m,hash) ) != 42 ) { //je v cachy return winner; } if (depth == (N*(N-1))/2 ) //vse je obarvene remiza //TODO diky poctu zbylych hran a tomu jake jsou hrozby by mohlo jit skoncit driv return 0; int x,y; int t = threats(player,m,u,v,&x,&y); if (t > 1){ if (player == GREEN) return 1; else return -1; } copy_graph(m2,m); hash2 = set_edge_color(player,m2,hash,u,v); if (t == 1){ winner = minimax_threat(next(player),m2,depth+1,hash2,x,y); } else { winner = minimax(next(player),m2,depth+1,hash2); } if ( depth % 3 == 1 ) put_into_cache(m2,hash2,winner); return winner; }
std::pair<Move, int> AIShell::IDSearchRecurse(int depth, int** state, int turn, int alpha, int beta, struct timeval& start) { std::pair<Move, int> inValid = std::make_pair(Move(-1, -1), -1); //AI_PIECE bigger better (MAX); HU_PIECE smaller better (MIN). int thisAlpha = alpha; int thisBeta = beta; // Create a copy of the current gameState int** tempGameState = new int*[numCols]; for (int col = 0; col < numCols; col++) { tempGameState[col] = new int[numRows]; for(int row = 0; row < numRows; row++) { tempGameState[col][row] = state[col][row]; } } // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} // Base Case for MinMax if (depth == 0) //At leaf node, actual move is not important since we just care the eval of this node { Move dummyMove; int hValue = heuristicEval(state, turn, start); std::pair<Move, int> dummyMoveEval = std::make_pair(dummyMove, hValue); return dummyMoveEval; } // Recursive Step for MinMax else { // Search for threats (k-1 in a row) on the board std::vector<int> evalNodes; std::vector<std::pair<int, int> > movesList = threats(tempGameState); // If there are no threats find all available moves if(movesList.size() == 0 && isUnderLimit(start)) { movesList = emptyBlock(tempGameState); } // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} for (int i = 0; i < movesList.size(); i++) { // If there's only 1 possible move. if(movesList.size() == 1) { Move bestMove(movesList[i].first, movesList[i].second); std::pair<Move, int> evalValue = std::make_pair(bestMove, 0); return evalValue; } // If there's more than 1 possible move. tempGameState[movesList[i].first][movesList[i].second] = turn; if (turn == AI_PIECE){ int nextLevelEval = IDSearchRecurse(depth - 1, tempGameState, HUMAN_PIECE, thisAlpha, thisBeta, start).second; // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} evalNodes.push_back(nextLevelEval); if (nextLevelEval >= thisBeta){ sort(movesList, i); evalNodes[0] = nextLevelEval; break; } if (nextLevelEval >= thisAlpha){ sort(movesList, i); evalNodes[0] = nextLevelEval; thisAlpha=nextLevelEval; } // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} } else{ int nextLevelEval = IDSearchRecurse(depth - 1, tempGameState, AI_PIECE, thisAlpha, thisBeta, start).second; // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} evalNodes.push_back(nextLevelEval); if (nextLevelEval <= thisAlpha){ sort(movesList, i); evalNodes[0] = nextLevelEval; break; } if (nextLevelEval <= thisBeta){ sort(movesList, i); evalNodes[0] = nextLevelEval; thisBeta = nextLevelEval; } // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} } tempGameState[movesList[i].first][movesList[i].second] = 0; //Set the block back // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} } if (turn == AI_PIECE) { Move bestMove(movesList[0].first, movesList[0].second); std::pair<Move, int> evalValue = std::make_pair(bestMove, evalNodes[0]); deleteBoard(tempGameState); // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} return evalValue; } else { Move bestMove(movesList[0].first, movesList[0].second); std::pair<Move, int> evalValue = std::make_pair(bestMove, evalNodes[0]); deleteBoard(tempGameState); // Makes sure time is still under the limit if(!isUnderLimit(start)) {return inValid;} return evalValue; } } }
int minimax(int player, luint m[4], int depth, int hash){ //1 zeleny vyhraje //0 remiza obarvene bez k4 //-1 cerveny vyhraje // print_adjacency_matrix(m,""); timer++; int max = -1; int min = 1; luint m2[4]; int hash2 = 0; if ( NORMALIZATION_FREQUENCY > 0 && depth % NORMALIZATION_FREQUENCY == 0) hash = normalization(m,hash); int winner; if ( (winner = get_from_cache(m,hash) ) != 42 && depth > 0){ // if ( depth % 3 == 1 && (winner = get_from_cache(m,hash) ) != 42 ) { //je v cachy a zaroven neni prazdny return winner; } if ( depth == (N*(N-1))/2 ) //vse je obarvene remiza return 0; for (uint i=0; i<N; i++) for (uint j=i+1; j<N; j++){ if (get_edge_color(m,i,j) == 0){ //pro vsechny neobarvene hrany (i,j) int x,y; int t = threats(player,m,i,j,&x,&y); if (t > 1){ if (player == GREEN) return 1; else return -1; } /* if (win(player,m,i,j)){ if (player == GREEN) return 1; else return -1; } */ copy_graph(m2,m); hash2 = set_edge_color(player,m2,hash,i,j); int tmp; if (t == 1){ tmp = minimax_threat(next(player),m2,depth+1,hash2,x,y); } else { tmp = minimax(next(player),m2,depth+1,hash2); } if (tmp > max) max = tmp; if (tmp < min) min = tmp; } } if (player == GREEN) winner = max; else winner = min; if ( depth % 3 == 1 ) put_into_cache(m2,hash2,winner); return winner; }