#include #include #include #include #include #include #include #include "Engine.h" Engine::Engine(){ Board* brd = new Board(); b = brd; alpha = INT_MIN; beta = INT_MAX; } void Engine::startGame(){ cout<<"WELCOME\n"; cout<<"1. Play against AI?\n"; cout<<"2. Watch AI vs AI?\n"; cout<<"Enter choice: \n"; int choice = -1; cin >> choice; cout << "OK" << endl; if (choice == 1) userGame(); else if (choice == 2) AIGame(); else { cout << "Please enter a valid choice.\n"; startGame(); } } void Engine::userGame(){ string move; bool gameOver = false; vector record; b->snapshot(record, *b); while (gameOver != true){ gameOver = b->isGameOver(); while(b->getTurn() == 'O' && !b->isValid()){ b->displayBoard(); cout<<"\nEnter command: "; cin>>move; cout << "\n"; b->interpret(move, *b); if(b->isValid()){ b->changeTurns(); b->resetTaken(); b->setValidFalse(); } } while(b->getTurn() == 'X' ){ //easyAI(); AI(3); } gameOver = b->isGameOver(); b->setValidFalse(); b->snapshot(record, *b); } b->displayBoard(); string s = ""; s += b->getTurn(); cout << "Game over. " + s + " wins!\n\n"; } void Engine::AIGame(){ bool gameOver = false; while (gameOver != true){ gameOver = b->isGameOver(); while(b->getTurn() == 'O'){ AI(3); } b->displayBoard(); sleep(1); while(b->getTurn() == 'X' ){ AI(3); } gameOver = b->isGameOver(); } } void Engine::AI(int depth){ Board* state = new Board(*b); moves m; MNode* root = new MNode(*state, m, 0); createMMTree(root, depth, 1); m = evaluateMMTree(root); //printTree(0, root); b->move(m); b->changeTurns(); b->resetTaken(); } void Engine::createMMTree(MNode* node, int depth, int alt){ MNode* temp; char max, min; bool cond = true; Board current = node->getState(); vector listOfMoves = current.viewPossibleMoves(); if (node->getType() == "max"){ if (node->getMMVal() <= alpha){ cond = false; } } else if (node->getType() == "min"){ if (node->getMMVal() >= beta){ cond = false; } } if (depth >= 0){ for (int i = 0; i < listOfMoves.size(); ++i){ if(current.getPiece(8 - listOfMoves[i].row, listOfMoves[i].column)->getType() == current.getTurn() && current.isThisMovePossible(8 - listOfMoves[i].row, listOfMoves[i].column, listOfMoves[i].moveType)){ if (cond){ current.resetTaken(); current = current.move(listOfMoves[i]); max = current.getTurn(); current.changeTurns(); min = current.getTurn(); /* if (current.checkTaken('X')) cout << "xtaken true\n"; if (current.checkTaken('O')) cout << "otaken true\n"; */ temp = new MNode(current, listOfMoves[i], current.evaluate(max, min)); if (alt == 1) temp->setType("max"); else if (alt == 1) temp->setType("min"); current.resetTaken(); node->addChild(temp); createMMTree(temp, --depth, alt * -1); current.changeTurns(); } } } } else { if (node->getType() == "max"){ if (node->getMMVal() > alpha){ alpha = node->getMMVal(); } } else if (node->getType() == "min"){ if (node->getMMVal() < beta){ beta = node->getMMVal(); } } } //cout << "alpha: " << alpha << "\n"; //cout << "beta: " << beta << "\n"; return; } moves Engine::evaluateMMTree(MNode* node){ //returns the move from children that maximizes evaluate() MNode* temp; moves m; int max = INT_MIN; int val; vector children = node->getChildren(); for (auto &c : children){ val = evaluateMMBranch(c, INT_MIN); if(val > max){ temp = c; max = val; } } return temp->getMove(); } int Engine::evaluateMMBranch(MNode* node, int max){ vector children = node->getChildren(); for (auto &c : children){ evaluateMMBranch(c, max); } if (node->getMMVal() > max) max = node->getMMVal(); return max; }