/* * This runs a heuristic AI on Othello */ Move *Player::doMoveHeuristic(Move *opponentsMove, vector<Move *> moves) { Move * bestmove = moves[0]; double bestScore = heuristicScore(moves[0], board->copy(), side); for(unsigned int i = 1; i < moves.size(); i++) { double score = heuristicScore(moves[i], board->copy(), side); if(score > bestScore) { bestmove = moves[i]; bestScore = score; } } board->doMove(bestmove, side); return bestmove; }
Move *Player::doMoveMinMax(Move *opponentsMove, vector<Move *> moves) { double lowestscore = -500000; Move * bestmove; vector<Move *> children; for(unsigned int i = 0; i < moves.size(); i++) { Board * b = board->copy(); double lowscore = 100000; b->doMove(moves[i], side); children = b->listMoves(opponentSide); for(unsigned int j = 0; j < children.size(); j++) { double score = heuristicScore(children[j], b->copy(), opponentSide); if(score < lowscore) lowscore = score; } if(lowscore > lowestscore) { bestmove = moves[i]; lowestscore = lowscore; } } board->doMove(bestmove, side); return bestmove; }
double Player::negaAB(int depth, int alpha, int beta) { vector<Move *> moves = board->listMoves(side); if (depth == 0) { // "evaluate"? return heuristicScore(moves[0], board->copy(), side); } for (unsigned int i = 0; i < moves.size(); i++) { double score = -negaAB(depth - 1, -beta, -alpha); if (score > alpha) { alpha = score; } if (score >= beta) { break; } } return alpha; }
/* * Compute the next move given the opponent's last move. Your AI is * expected to keep track of the board on its own. If this is the first move, * or if the opponent passed on the last move, then opponentsMove will be NULL. * * msLeft represents the time your AI has left for the total game, in * milliseconds. doMove() must take no longer than msLeft, or your AI will * be disqualified! An msLeft value of -1 indicates no time limit. * * The move returned must be legal; if there are no valid moves for your side, * return NULL. */ Move *Player::doMove(Move *opponentsMove, int msLeft) { /* * TODO: Implement how moves your AI should play here. You should first * process the opponent's opponents move before calculating your own move */ std::clock_t start; double duration; start = std::clock(); Move *myMove = NULL; if(testingMinimax || minimaxPlaying){ // Process opponent's move (doMove handles NULL moves) board->doMove(opponentsMove, opp_side); // Call minimax int max_depth = 4; std::pair<int, Move*> best_choice = minimax(board, 0, max_depth, true); myMove = best_choice.second; // set board to the best board board->doMove(myMove, my_side); } else{ // Process opponent's move (doMove handles NULL moves) board->doMove(opponentsMove, opp_side); // Calculate my valid moves std::vector<Move*> valid_moves = findValid(my_side, board); if(!valid_moves.empty() && dumbPlaying){ // Randomly choose a valid move to play int index = rand() % valid_moves.size(); myMove = valid_moves[index]; } if(!valid_moves.empty() && !dumbPlaying){ // choose valid move using heuristic //find the best move out of all the valid moves std::vector<Move*>::iterator i; int best_score = std::numeric_limits<int>::min(); Move *curr; int curr_score; for(i = valid_moves.begin(); i != valid_moves.end(); i++){ curr = *i; curr_score = heuristicScore(curr, my_side); if(curr_score > best_score){ best_score = curr_score; myMove = curr; } } } // Process my own move board->doMove(myMove, my_side); fprintf(stderr,"Using %s, Iago (%s) chose Move: (%d, %d)\n", (dumbPlaying) ? "random choice": "heuristic", (my_side == BLACK) ? "Black": "White", myMove->getX(), myMove->getY()); }// closes else duration = (std::clock() - start) / (double)CLOCKS_PER_SEC; fprintf(stderr, "Time to make move: %f seconds\n", duration); return myMove; }