From 590a4473ff37ea30c07a4af6b5a84dba569df742 Mon Sep 17 00:00:00 2001 From: AnasImloul Date: Tue, 31 Oct 2023 22:20:35 +0100 Subject: [PATCH] Added multithreading optimization --- grid.cpp | 10 ++++++-- main.cpp | 6 ++--- move.cpp | 76 +++++++++++++++++++++++++++++++++++++------------------- move.h | 2 +- 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/grid.cpp b/grid.cpp index 4be8a18..b95ff04 100644 --- a/grid.cpp +++ b/grid.cpp @@ -55,10 +55,16 @@ void grid::show() { long long value = (tiles[i * SIZE + j] != 0 ? (1 << tiles[i * SIZE + j]) : 0); std::cout << value << std::string(maxLength1 - length(value), ' ') << " "; } - for (int i = 0; i < 1 + maxLength1 / 3; i++) + if (i + 1 == SIZE) { std::cout << std::endl; + } else { + for (int i = 0; i < 1 + maxLength1 / 3; i++) + std::cout << std::endl; + } } - std::cout << std::endl; + std::cout << "Score: " << score << std::endl; + + } bool grid::up() { diff --git a/main.cpp b/main.cpp index b2893eb..4244bc7 100644 --- a/main.cpp +++ b/main.cpp @@ -12,17 +12,17 @@ void fastIO() { } int main() { - std::srand(std::time(nullptr)); + // std::srand(std::time(nullptr)); fastIO(); grid g; int move; do { - move = move::bestMove(g, 8); + move = move::bestMove(g, 12); g.move(move); g.show(); - std::cout << "Score: " << g.getScore() << std::endl; + std::cout << std::endl; } while (move != -1); } diff --git a/move.cpp b/move.cpp index 9f7c1c4..e94b435 100644 --- a/move.cpp +++ b/move.cpp @@ -1,47 +1,73 @@ -// -// Created by user on 29/10/2023. -// - #include "move.h" #include +#include +#include +#include #define max(a, b) ((a) > (b) ? (a) : (b)) namespace move { int bestMove(grid& g, int depth) { - int64_t bestScore = 0; - int bestDir = -1, calls = 0; - bestMoveHelper(g, depth, bestScore, bestDir, -1, calls); - std::cout << "calls: " << calls << std::endl; + std::vector threads; + int64_t scores[16]; + for (int i = 0; i < 16; i++) scores[i] = -1; + + for (int first : DIRECTIONS) { + for (int second : DIRECTIONS) { + threads.emplace_back([&](int dir) { + grid g1(g); + if (g1.move(dir / 4)) { + grid g2(g1); + if (g2.move(dir % 4)) { + int64_t score = -1; + bestScore(g2, depth - 2, score); + scores[dir] = score; + } else { + int64_t score = evaluate(g1) >> depth; + scores[dir] = score; + } + } + }, first * 4 + second); + } + } + + for (auto& thread : threads) { + thread.join(); + } + + int bestDir = -1; + int64_t _bestScore = -1; + + for (int i = 0; i < 16; i++) { + int64_t score = scores[i]; + + if (score > _bestScore) { + _bestScore = score; + bestDir = i / 4; + } + } + return bestDir; + } inline int64_t evaluate(grid& g) { return (g.getEmpty() << 16) + g.getScore(); } namespace { - int bestMoveHelper(const grid& g, int depth, int &bestScore, int &bestDir, int move) { - if (depth == 0 || g.isBlocked()) { - return evaluate(g); - } + void bestScore(grid& g, int depth, int64_t& currentBestScore) { - if (move == -1) { - // if the move is -1, we are at the root of the tree - // we will have dynamic depth based on the number of empty tiles - // the less empty tiles, the more depth - depth = max(depth * (SIZE - g.getEmpty() / SIZE) / SIZE, 4); - } + int64_t score = evaluate(g) >> depth; + currentBestScore = max(currentBestScore, score); + + if (depth == 0) + return; for (int dir : DIRECTIONS) { grid g1(g); - g1.move(dir); - int score = bestMoveHelper(g1, depth - 1, bestScore, bestDir, (move == -1 ? dir : move)); - if (score > bestScore) { - bestScore = score; - bestDir = move; + if (g1.move(dir)) { + bestScore(g1, depth - 1, currentBestScore); } } - - return bestScore; } } diff --git a/move.h b/move.h index d80fedd..154530f 100644 --- a/move.h +++ b/move.h @@ -13,7 +13,7 @@ namespace move { inline int64_t evaluate(grid &g); namespace { - void bestMoveHelper(grid& g, int depth, int64_t &bestScore, int &bestDir, int move, int& calls); + void bestScore(grid& g, int depth, int64_t& currentBestScore); } } \ No newline at end of file