Exemplo n.º 1
0
bool Table::shouldFinishGame(PieceColor pieceColor)
{
    if(isGameFinished(pieceColor) || getAllPossibleMoves(m_array, getOppositeColor(pieceColor)).empty())
    {
        return true;
    }
    return false;
}
Exemplo n.º 2
0
void AIRandomPlayer::requestMove(PieceColor moveType)
{
    assert(m_array);
    auto gameLogic = m_gameLogic.lock();

    std::vector<int> scores;
    auto lockedGameLogic = m_gameLogic.lock();
    std::vector<PieceMove> moves = lockedGameLogic->getAllPossibleMoves(*m_array, moveType);

    auto move = moves.at(rand() % moves.size());
    std::vector<Position> subMoves{move.subMoves().begin()+1, move.subMoves().end()};
    lockedGameLogic->movePiece(move.source(), subMoves, moveType);

}
Exemplo n.º 3
0
void AIMediocrePlayer::requestMove(PieceColor moveType)
{
    assert(m_array);
    auto gameLogic = m_gameLogic.lock();

    std::vector<int> scores;
    auto lockedGameLogic = m_gameLogic.lock();
    std::vector<PieceMove> moves = lockedGameLogic->getAllPossibleMoves(*m_array, moveType);

    std::vector<std::future<int>> futures;
    for(const auto& move: moves)
    {
        Array copyOfArray = *m_array;
        copyOfArray.move(move.source().m_row, move.source().m_col, move.destination().m_row, move.destination().m_col);
        for(const auto& pos: move.capturedPieces())
        {
            copyOfArray.erase(pos.m_row, pos.m_col);
        }

        int newScore = move.numberOfCapturedPieces();

        auto score = std::async(std::launch::async,
                                &minMaxWithAlphaBetaPruning,
                                lockedGameLogic,
                                copyOfArray,
                                m_maxDepth,
                                newScore,
                                getOppositeColor(moveType),
                                moveType,
                                gMinusInfinity,
                                gPlusInfinity);
        futures.push_back(std::move(score));
    }

    for(auto& future: futures)
    {
        auto result = future.get();
        scores.push_back(result);
    }

    auto it = std::max_element(scores.begin(), scores.end());

    PieceMove move = moves.at(std::distance(scores.begin(), it));
    std::vector<Position> subMoves{move.subMoves().begin()+1, move.subMoves().end()};

    lockedGameLogic->movePiece(move.source(), subMoves, moveType);
}
Exemplo n.º 4
0
	std::pair<int, int> algorithm(const Board& board, int depth, bool whiteOnTurn)
	{
		Move currentBestMove = { 0, 0, 0 }; // Container for best value and the move to get there

		int a = MIN; // Alpha
		int b = MAX; // Beta
		currentBestMove.value = (whiteOnTurn) ? a : b;

		// 1. Get number of threads that system can manage
		unsigned int num_of_threads = THREADS;
		std::srand((int)std::time(0));

		// 2. Get all possible moves and divide them as tasks to threads
		std::vector<Move> possibleMoves = getAllPossibleMoves(board, whiteOnTurn);
		// In other cases can proceed to dividing tasks for threads
		taskVectors.clear(); // Must be cleared so it's empty on start
		taskVectors = divideForThreads(possibleMoves, (int)num_of_threads);

		// 3. Create threadpool and run tasks with threads
		std::vector<std::thread> threads;

		// Lambda
		auto lambda = [depth, whiteOnTurn](Board board, int i, int la, int lb)
		{
			// This is what the thread does to its tasks 
			// This also works as 1st level of algorithm (because of alphaBeta structure)
			std::srand((int)std::time(0)); // Use current time as a seed for random
			
			// Copy taskVektor so it can be used
			threadMutex.lock();
			std::vector<Move> tasks = taskVectors[i];
			threadMutex.unlock();
			Move bestThreadMove = { 0, 0, 0};
			bestThreadMove.value = (whiteOnTurn) ? la : lb;

			for (auto move : tasks) {
				move.value = (whiteOnTurn) ? la : lb; // For white turn=>MIN black=>MAX
				Board new_board = board;
				new_board.movePiece(move.origin, move.destination);
				new_board.updateState(move.destination, 1);

				int temp = alphaBeta(new_board, depth - 1, la, lb, !whiteOnTurn);

				// Recursive part depth needs to decrease now depth at its maximum
				if (whiteOnTurn) {
					if ((bestThreadMove.value < temp) || (bestThreadMove.value == temp && (rand() % 8 == 1))) {
						bestThreadMove = move;
						bestThreadMove.value = temp;
					}
					la = std::max(la, bestThreadMove.value);
				} else {
					if ((bestThreadMove.value > temp) || (bestThreadMove.value == temp && (rand() % 8 == 1))) {
						bestThreadMove = move;
						bestThreadMove.value = temp;
					}
					lb = std::min(lb, bestThreadMove.value);
				}

				if (lb <= la)
				{
					break; // Cut off bad branch
				}

				// Randomly pick if as good as current

			}

			threadMutex.lock(); // Must be logged so that threads wont do this same time
			{
				taskVectors[i].clear();
				taskVectors[i].push_back(bestThreadMove);
			}
			threadMutex.unlock();
		};

		// Create threads and push them in vector
		for (unsigned int i = 0; i < taskVectors.size(); i++) {
			// Some magic with lambda functions
			threads.push_back(std::thread(lambda, board, i, a, b));
			//std::cout << "Started thread number " << i + 1 << std::endl;
		}

		//int i = 1; //This is for the cout below
		// 4. Wait threads to finish
		for (auto thread = threads.begin(); thread != threads.end(); thread++)
		{
			//std::cout << "Waiting for thread number " << i << " to finish." << std::endl;
			thread->join();
			//std::cout << "Thread number " << i++ << " finished." << std::endl;

		}

		// 5. Choose best value
		for (auto list : taskVectors) {
			for (auto move : list) {
				// White turn
				if (move.value > currentBestMove.value && whiteOnTurn) {
					currentBestMove = move; // Replace with better one
				}
				// Black turn
				else if (move.value < currentBestMove.value && !whiteOnTurn) {
					// To have some random factor if same values
					currentBestMove = move;
				}
				else if (move.value == currentBestMove.value && (rand() % 8 == 1)) {
					currentBestMove = move;
				}
			}
		}
		if (currentBestMove.origin == 0 && currentBestMove.destination == 0) {
			std::cout << "Illegal move [0,0]" << std::endl;
		}
		//std::cout << "Returning with move [" << currentBestMove.origin << "," << currentBestMove.destination <<  "]" << ", its value is " << currentBestMove.value << std::endl;

		return std::make_pair(currentBestMove.origin ,currentBestMove.destination);
	}
Exemplo n.º 5
0
void AIBestPlayer::requestMove(PieceColor moveType)
{
    assert(m_array);
    auto gameLogic = m_gameLogic.lock();


    std::vector<int> scores;
    auto lockedGameLogic = m_gameLogic.lock();
    std::vector<PieceMove> moves = lockedGameLogic->getAllPossibleMoves(*m_array, moveType);

    std::experimental::optional<std::pair<std::vector<Position>, int>> foundMove = bestMoves::findMove(*m_array, moveType);

    if(!foundMove || (foundMove && foundMove->second < m_maxDepth))
    {
        std::cout << "computation of best move" << std::endl;
        std::vector<std::future<int>> futures;
        for(const auto& move: moves)
        {
            Array copyOfArray = *m_array;
            copyOfArray.move(move.source().m_row, move.source().m_col, move.destination().m_row, move.destination().m_col);
            for(const auto& pos: move.capturedPieces())
            {
                copyOfArray.erase(pos.m_row, pos.m_col);
            }

            int newScore = move.numberOfCapturedPieces();

            auto score = std::async(std::launch::async,
                                    &minMaxWithAlphaBetaPruning,
                                    lockedGameLogic,
                                    copyOfArray,
                                    m_maxDepth,
                                    newScore,
                                    getOppositeColor(moveType),
                                    moveType,
                                    gMinusInfinity,
                                    gPlusInfinity);
            futures.push_back(std::move(score));
        }

        for(auto& future: futures)
        {
            auto result = future.get();
            scores.push_back(result);
        }

        auto it = std::max_element(scores.begin(), scores.end());

        PieceMove move = moves.at(std::distance(scores.begin(), it));
        std::vector<Position> subMoves{move.subMoves().begin()+1, move.subMoves().end()};
        lockedGameLogic->movePiece(move.source(), subMoves, moveType);
    }
    else
    {
        std::vector<Position>& positions = foundMove->first;
        for(const auto& move: moves)
        {
            if(positions == move.subMoves())
            {
                std::cout << "used saved best move" << std::endl;
                std::vector<Position> subMoves{move.subMoves().begin()+1, move.subMoves().end()};
                lockedGameLogic->movePiece(move.source(), subMoves, moveType);
            }
        }
    }
}