void OthelloPlayerLOM::returnPlay(const OthelloBoard<8, 8>& board, int& x, int& y) { std::map<int, std::vector<std::pair<int, int>>> finalMove; unsigned char lastPlayer = board.getLastPlayer(); unsigned char player; if(lastPlayer == 1) player = 2; else player = 1; for(auto& move : board.getValidPlays()) { OthelloBoard<8, 8> hBoard(board); hBoard.play(player, move.first, move.second); int nMoves = hBoard.avaliableMoves(lastPlayer); if((move.first == 0 || move.first == 7) && (move.second == 0 || move.second == 7)) { nMoves -= 20; } for(auto& opMove : hBoard.getValidPlays()) { if((opMove.first == 0 || opMove.first == 7) && (opMove.second == 0 || opMove.second == 7)) { nMoves += 100; } else if(opMove.first == 0 || opMove.first == 7 || opMove.second == 0 || opMove.second == 7) { nMoves += 10; } } finalMove[nMoves].push_back(move); } x = finalMove.begin()->second.front().first; y = finalMove.begin()->second.front().second; }
int score_gen(const OthelloBoard& board,Turn turn) { int r_score = board.getRedCount(); int b_score = board.getBlackCount(); if(turn == RED) { if (b_score == 0) { return 100; } if(r_score == 0) { return -100; } return r_score-b_score; } else { if (r_score == 0) { return 100; } if(b_score == 0) { return -100; } return b_score-r_score; } }
bool isDiagonalsFilled(int i, int j, OthelloBoard& curBoard ) { int k = i, l = j; while(0 <= k && k < 8 && 0 <= l && l < 8){ if(curBoard.get(k,l) == EMPTY) return false; k++, l++; } k = i, l = j; while(0 <= k && k < 8 && 0 <= l && l < 8){ if(curBoard.get(k,l) == EMPTY) return false; k++, l--; } k = i, l = j; while(0 <= k && k < 8 && 0 <= l && l < 8){ if(curBoard.get(k,l) == EMPTY) return false; k--, l++; } k = i, l = j; while(0 <= k && k < 8 && 0 <= l && l < 8){ if(curBoard.get(k,l) == EMPTY) return false; k--, l--; } return true; }
int MyBot::countDifference(Turn turn, const OthelloBoard& board){ int redCount = board.getRedCount(); int blackCount = board.getBlackCount(); if(turn == RED){ return redCount - blackCount; } else { return blackCount - redCount; } }
int MyBot::evaluationFunction(Turn turn, const OthelloBoard& board){ int sum = 0; Turn opp = other(turn); for(int i = 0; i < 8; i++){ for(int j = 0; j < 8; j++){ if(turn == board.get(i,j)){ sum = sum + weights[i][j]; } else if(opp == board.get(i,j)){ sum = sum - weights[i][j]; } } } return sum; }
/** * Create the children of the node, corresponding to all possible moves from node board. * \return True if the node has been expand, false if no move was possible. **/ bool OthelloSearchNode::expandNode() { using namespace std; list<OthelloAction*> * moves = _board->getMoves(); if(moves == NULL) return false; _children = new list<OthelloSearchNode*>(); for(list<OthelloAction*>::iterator it = moves->begin(); it != moves->end(); ++it) { OthelloBoard * p = new OthelloBoard(*_board); (*it)->apply(p); p->changePlayer(); _children->push_front(new OthelloSearchNode(_level + 1, p, *it)); } delete moves; return true; }
Move MyBot::play(const OthelloBoard& board) { ourTurn = turn; store.clear(); threadSuccessfull = false; if (!strtGame) { pthread_join(RGThread, NULL); getPrevMove(board); setPlyDepth(); if(OpponentMoveDone){ pos = getIndex(); if(pos <= threadDone && pos != -1) threadSuccessfull = true; } } else if (ourTurn == BLACK) { strtGame = false; --gameMovesDone; setPlyDepth(); PrevBoard = OthelloBoard(board); list<Move> moveLst = PrevBoard.getValidMoves(ourTurn); list<Move>::iterator it = moveLst.begin(); int randNo = (rand() % 4); for (int i = 0; i < randNo - 1; ++it, ++i); FinalMove.x = it->x, FinalMove.y = it->y; PrevBoard.makeMove(ourTurn, FinalMove); ++gameMovesDone; /* Initializing the thread to RG opponenet before returning the move */ RGThreadStatus = pthread_create(&RGThread, NULL, threadFunc, (void*)NULL); return FinalMove; } strtGame = false; PrevBoard = OthelloBoard(board); Node* root = new Node(PrevBoard, ourTurn); if(!shallowDepthDone) shallowDepth(root); alphabetaMiniMax(root, 0, MIN_NUM, MAX_NUM, 0); PrevBoard.makeMove(ourTurn, FinalMove); ++gameMovesDone; /* Initializing the thread to RG opponenet before returning the move */ RGThreadStatus = pthread_create(&RGThread, NULL, threadFunc, (void*)NULL); return FinalMove; }
void getPrevMove(const OthelloBoard& board) { int i, j; OpponentMoveDone = true; int numberOfMoves = 0; for (i = 0; i < 8; ++i) { for (j = 0; j < 8; ++j) { if (PrevBoard.get(i, j) == EMPTY && board.get(i, j) != PrevBoard.get(i, j)) { PrevMove.x = i, PrevMove.y = j; ++numberOfMoves; if(numberOfMoves > 1) OpponentMoveDone = false; } } } gameMovesDone += numberOfMoves; if(numberOfMoves == 0) OpponentMoveDone = false; }
int getIndex(){ list<Move> moveLst = PrevBoard.getValidMoves(other(ourTurn)); int i = 0; for(list<Move>::iterator it = moveLst.begin(); it != moveLst.end(); ++it, ++i){ if(it->x == PrevMove.x && it->y == PrevMove.y) return i; } return -1; }
Move MyBot::play( const OthelloBoard& board ) { start = clock(); cout<<"My turn\n"; board.print(turn); while(double(clock() - start)/CLOCKS_PER_SEC<2); start = clock(); alphabeta(board,DEPTH,-1000,1000,turn,turn); return bestMove; }
int main(int argc, char* argv[]) { // C++11 introduces the keyword 'auto' to use "type inference" to select // the type of a variable automatically when it is declared. auto i = 10; // i is of type int, because the rhs is int. auto d = 10.0; // d is of type double // For primitive types, this doesn't make much sense to use, so DON'T GO // OVERBOARD and make all variables auto. For one, you must initialize an // auto variable when declared. // auto unknown; <---- what type is this variable? Not allowed. // Second, sometimes the inferred type is misleading... auto s = "Hello, world!"; // Can you guess what type s is? // Third, can't construct objects on the stack as easily... // Suppose I want to replace "Rational r(1, 3); with auto. // auto r(1,3); won't compile, why? // So when is auto useful? // If the return type of a function is obvious, but tedious to use. // Imagine I'm in your Othello project. OthelloBoard board; const vector<OthelloMove*> *history = board.GetMoveHistory(); // ugly! auto hist = board.GetMoveHistory(); // pretty! // For the same reason, auto is useful with iterators. for (auto itr = hist->rbegin(); itr != hist->rend(); itr++) { // printing in reverse order, C++11 style! } }
Move MyBot::play(const OthelloBoard& board ) { list<Move> moves = board.getValidMoves( turn ); if(moves.size()==0) return Move::pass(); OthelloBoard b; list<Move>::iterator it; int currbest = POSLARGE; Move *cm = 0; bool firstRun = true; int val; priority_queue<MovePair> pq; for(it=moves.begin(); it!=moves.end(); it++){ b = board; b.makeMove(turn,*it); int score = weights[it->x][it->y]; MovePair *tempm = new MovePair(&(*it), score); pq.push(*tempm); } while(!pq.empty()){ Move* m = pq.top().m; pq.pop(); b = board; b.makeMove(turn,*m); val = alphaBeta(other(turn), b, NEGLARGE, val, PLY); if(val<currbest || firstRun){ currbest = val; cm = m; firstRun = false; } } if(cm==0) cout<<"cm is null!!"<<endl<<moves.size()<<endl; return *cm; }
int MyBot::alphaBeta(Turn turn, const OthelloBoard& board, int alpha, int beta, int ply) { if(ply==0) { return evaluationFunction(turn, board); } else { list<Move> moves = board.getValidMoves(turn); int noOfMoves = moves.size(); if(noOfMoves == 0) { list<Move> oppMoves = board.getValidMoves(other(turn)); if(oppMoves.size()!= 0){ return (- (alphaBeta (other(turn), board, -beta, -alpha, ply-1))); } else return finalValue(turn, board); } else { list<Move>::iterator it = moves.begin(); for(; it != moves.end(); it++){ OthelloBoard board2 = board; board2.makeMove(turn, *it); //val is alpha in the case of max and beta in the case of min int val = - alphaBeta(other(turn), board2, - beta, -alpha, (ply-1)); if(val >= beta) return val; if(val >= alpha) { alpha = val; if(ply == PLY) bestMove = &(*it); } } return alpha; } } }
int main(int argc, char* argv[]){ //Welcome message cout << "Welcome to Othello!" << endl; //OthelloBoard class object OthelloBoard board; //OthelloView class object OthelloView view(&board); //Vector move pointer vector<OthelloMove *> move; //User input string input; while (!(board.IsFinished())) { //Display current board cout << view << endl; //Get all possible moves board.GetPossibleMoves(&move); //Possible moves variable string possibleMoves; for(OthelloMove *mov: move){ //Retrieving all possible moves possibleMoves += *mov; //Removing all possible moves from the heap delete mov; } //Clear all move vector pointers move.clear(); if (board.GetNextPlayer() == board.BLACK) { //Black's move cout << "\nBlack's turn" << endl; } else { //White's move cout << "\nWhite's turn" << endl; } //Display all possible moves cout << "Possible moves:\n" << possibleMoves << endl; cout << "Enter a command: "; //Get user input getline(cin, input); cout << endl; //Command input string choice; //new move position int position = board.EMPTY; for (int index = board.EMPTY; index < input.length(); index++){ if (input[index] == ' ') { //Retrieving new move position position = index + 1; break; } //Retrieving command input choice += input[index]; } if (choice == "move") { //Creating new move OthelloMove *newMove = board.CreateMove(); try { //Retrieving new move (*newMove) = input.substr(position); } catch(OthelloException &error) { //Invalid new move cout << error.what() << endl; delete newMove; } //Get all new possible moves board.GetPossibleMoves(&move); bool equal = false; for (vector<OthelloMove *>::iterator itr = move.begin(); itr != move.end(); ++itr){ //Store all possible new moves OthelloMove *temp = *itr; if (*newMove == *temp && !equal) { //Apply new move onto the board board.ApplyMove(newMove); //Valid new move equal = true; } //Removing all possible moves on the heap delete temp; } if (!equal) { cout << "\nInvalid input" << endl; //Removing invalid new move delete newMove; } //Clear all move vector pointers move.clear(); } else if (choice == "undo") { //Number of undoes int number = stoi(input.substr(position)); if (number > board.GetMoveCount()){ //Max number of undoes number = board.GetMoveCount(); } while(number > board.EMPTY) { //Undo latest move board.UndoLastMove(); //Next undo move number--; } } else if (choice == "showValue") { //Display current board value cout << "Board Value: " << board.GetValue() << endl; } else if (choice == "showHistory") { //History of all moves apply const vector<OthelloMove *> *mov = board.GetMoveHistory(); //Number moves applied to the board int index = board.GetMoveCount(); for (vector<OthelloMove *>::const_reverse_iterator temp = mov->crbegin(); temp != mov -> crend(); ++temp){ //Getting latest move's history OthelloMove *m = *temp; if (index % (board.BLACK + board.BLACK) == 0) { //White history movement cout << "White: " << (string) *m << endl; } else { //Black history movement cout << "Black: " << (string) *m << endl; } //Next player's history movement index--; } } else { //Exit the game cout << "Thank you for playing" << endl; break; } } if (board.GetValue() > board.EMPTY) { //Black won the game cout << "\nBlack wins!" << endl; } else if (board.GetValue() < board.EMPTY){ //White won the game cout << "\nWhite wins!" << endl; } else { //Tie game cout << "\nIt's a tie!" << endl; } }
int main(int argc, char* argv[]) { // Initialization OthelloBoard board; // the state of the game board OthelloView v(&board); // a View for outputting the board via operator<< string userInput; // a string to hold the user's command choice vector<OthelloMove *> possMoves; // a holder for possible moves do { string command1, command2; //Clearing possible moves and freeing memory for (OthelloMove *move : possMoves) { delete move; } possMoves.clear(); istringstream iss; bool isValidMove = false; cout << v << endl; board.GetPossibleMoves(&possMoves); cout << "Possible moves for " << ((board.GetNextPlayer() == -1) ? "White: " : "Black: ") << endl; for (OthelloMove *move : possMoves) { cout << (string) *move << " "; } cout << endl; cout << "Enter a command" << endl; getline(cin, userInput); iss.str(userInput); iss >> command1; if (command1 == "move") { iss >> command2; OthelloMove *m = board.CreateMove(); try { *m = command2; for (OthelloMove *move : possMoves) { if (*m == *move) { isValidMove = true; } } if (isValidMove){ board.ApplyMove(m); } else { cout << "Not a valid move." << endl; delete m; continue; } } catch (OthelloException e) { cout << e.what() << endl; delete m; } } else if (command1 == "undo") { int times; iss >> times; for (int i = times; i > 0; i --) { if (board.GetMoveHistory()->size() == 0) break; else board.UndoLastMove(); } }
int alphabeta(const OthelloBoard& board,int depth,int alpha,int beta,Turn turn ,Turn max_player) { Turn next_turn = other(turn); int k; if (depth == 0) { return score_gen(board,max_player); } if(board.getValidMoves( turn ).empty() && board.getValidMoves( other( turn ) ).empty()) { return score_gen(board,max_player); } list<Move> Moves = board.getValidMoves(turn); int temp; OthelloBoard temp_board ; if (turn == max_player) { if(!Moves.empty()) { list<Move>::iterator it = Moves.begin(); if(depth == DEPTH) { bestMove = Move(*it); } for( ; it!=Moves.end() ; it++) { temp_board = board; temp_board.makeMove(turn,*it); /* if(distance(it,Moves.end())<DEPTH && depth == DEPTH) { k = DEPTH - distance(it,Moves.end()); } else { k=0; }*/ if(double(clock() - start)/CLOCKS_PER_SEC>4.98) { // cout<<"broke"; break; } temp = alphabeta(temp_board, depth - 1 , alpha, beta, next_turn, max_player); if(alpha < temp) { alpha = temp; if(depth == DEPTH) { bestMove = Move(*it); } } if (beta<=alpha) { break; } } return alpha; } } else { if(!Moves.empty()) { for( list<Move>::iterator it = Moves.begin() ; it!=Moves.end() ; it++) { temp_board = board; temp_board.makeMove(turn,*it); if(double(clock() - start)/CLOCKS_PER_SEC>4.98) { // cout<<"broke"; break; } temp = alphabeta(temp_board, depth - 1, alpha, beta, next_turn, max_player); if( beta > temp) { beta = temp; } if (beta<=alpha) { break; } } return beta; } } }
/*Function to calculate 2 levels of Moves*/ void* threadFunc(void* ptr){ int i, j; shallowDepthDone = false; threadDone = threadDone2 = -1; memset(thread2Done,false, sizeof(thread2Done)); Turn otherTurn = other(ourTurn); immediateSucc = PrevBoard.getValidMoves(otherTurn); list<Move>::iterator it, kj; OthelloBoard saveBoard = PrevBoard; for(i = 0, it = immediateSucc.begin(); it != immediateSucc.end(); ++it, ++i){ PrevBoard.makeMove(otherTurn, *it); moveLst1[i] = PrevBoard.getValidMoves(ourTurn); PrevBoard = saveBoard; ++threadDone; } for(i = 0, kj = immediateSucc.begin() ; kj != immediateSucc.end(); ++kj, ++i ){ PrevBoard.makeMove(otherTurn, *kj); OthelloBoard saveBoard1 = PrevBoard; for( j = 0, it = moveLst1[i].begin(); it != moveLst1[i].end(); ++it, ++j){ PrevBoard.makeMove(ourTurn, *it); moveLst2[i][j] = PrevBoard.getValidMoves(otherTurn); PrevBoard = saveBoard1; } thread2Done[i] = true; ++threadDone2; PrevBoard = saveBoard; } return NULL; }