#include #include #include #include #include #include #include #include "Engine.h" #include "Parser.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<<"Enter AI difficulty: \n"; int difficulty; cin >> difficulty; cout << "OK" << endl; if (choice == 1) userGame(difficulty); else if (choice == 2) AIGame(difficulty); else { cout << "Please enter a valid choice.\n"; startGame(); } } void Engine::userGame(int difficulty){ string move; bool gameOver = false; vector record; b->snapshot(record, *b); cin.ignore(); cin.clear(); while (gameOver != true){ gameOver = b->isGameOver(); while(b->getTurn() == 'O' && !b->isValid()){ b->displayBoard(); cout<<"\nEnter command: "; cin.clear(); getline(cin, move); cout << "\n"; parse(move, *b); if(b->isValid()){ b->changeTurns(); b->resetTaken(); b->setValidFalse(); } b->displayBoard(); } while(b->getTurn() == 'X' ){ AI(difficulty); 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(int difficulty){ bool gameOver = false; while (gameOver != true){ gameOver = b->isGameOver(); while(b->getTurn() == 'O'){ AI(difficulty); } b->displayBoard(); sleep(1); while(b->getTurn() == 'X' ){ AI(difficulty); } b->displayBoard(); sleep(1); gameOver = b->isGameOver(); } string s = ""; s += b->getTurn(); cout << "Game over. " + s + " wins!\n\n"; } void Engine::AI(int depth){ if (depth == -1) depth = INT_MAX; Board* state = new Board(*b); moves m; MNode* root = new MNode(*state, m, 0); this->resetAB(); createMMTree(root, depth, 1); m = evaluateMMTree(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(listOfMoves[i].row, listOfMoves[i].column)->getType() == current.getTurn() && current.isThisMovePossible(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(); 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); alt = alt * -1; createMMTree(temp, --depth, alt); 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(); } } } return; } moves Engine::evaluateMMTree(MNode* node){ //returns the move from children that maximizes evaluate() MNode* temp; int max = INT_MIN; int min = INT_MAX; int val; vector children = node->getChildren(); for (auto &c : children){ val = evaluateMMBranch(c, INT_MIN, INT_MAX); if(val > max){ temp = c; max = val; } if(val < min){ temp = c; min = val; } } return temp->getMove(); } int Engine::evaluateMMBranch(MNode* node, int max, int min){ vector children = node->getChildren(); for (auto &c : children){ evaluateMMBranch(c, max, min); } if (node->getMMVal() > max) max = node->getMMVal(); if (node->getMMVal() < min) min = node->getMMVal(); return max; } void Engine::resetAB(){ alpha = INT_MIN; beta = INT_MAX; }