From 0528ed43bb13edd89dfa8a38b9bfca6ba7fd83d6 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 30 Jul 2026 17:19:56 +0200 Subject: optimazing --- src/bot.cpp | 41 +++++++--------- src/bot.hpp | 2 +- src/moves.cpp | 150 ++++++++++++++++++++++++++++++++-------------------------- src/moves.hpp | 15 +++--- 4 files changed, 110 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/bot.cpp b/src/bot.cpp index f05c303..61c38fa 100644 --- a/src/bot.cpp +++ b/src/bot.cpp @@ -11,7 +11,7 @@ #include constexpr int DEFAULT_DEPTH = 4; -constexpr int Q_DEPTH_LIMIT = 6; +constexpr int Q_DEPTH_LIMIT = 3; constexpr int PAWN_VALUE = 100; constexpr int KNIGHT_VALUE = 320; @@ -117,8 +117,8 @@ int ScoreMove(const Game *board, const Move &move) { return score; } -std::vector GetSortedLegalMoves(Game *g) { - auto moves = GetLegalMoves(g); +std::vector GetSortedLegalMoves(Game *g, bool generateQuietMoves) { + auto moves = GetLegalMoves(g, generateQuietMoves); if (moves.empty()) { return moves; } @@ -167,18 +167,13 @@ int quiescenceSearch(Game *b, int Qdepth) { if (Qdepth >= Q_DEPTH_LIMIT) { return standPat; } - std::vector attackMoves; - for (Move move : GetSortedLegalMoves(b)) { - if (b->pieces[PositionToIndex(move.To)].type != NONEPIECE) { - attackMoves.push_back(move); - } - }; + std::vector attackMoves = GetSortedLegalMoves(b, false); if (attackMoves.empty()) { return standPat; } - int bestEval = b->turn ? std::numeric_limits::lowest() - : std::numeric_limits::max(); + int bestScore = b->turn ? std::numeric_limits::lowest() + : std::numeric_limits::max(); if (b->turn) { for (Move move : attackMoves) { @@ -187,7 +182,7 @@ int quiescenceSearch(Game *b, int Qdepth) { int eval = quiescenceSearch(b, Qdepth + 1); UnMakeMove(undo, b); - bestEval = std::max(bestEval, eval); + bestScore = std::max(bestScore, eval); } } else { for (Move move : attackMoves) { @@ -196,11 +191,11 @@ int quiescenceSearch(Game *b, int Qdepth) { int eval = quiescenceSearch(b, Qdepth + 1); UnMakeMove(undo, b); - bestEval = std::min(bestEval, eval); + bestScore = std::min(bestScore, eval); } } - return bestEval; + return bestScore; } int minimax(int depth, Game *b, float alpha, float beta) { @@ -221,13 +216,13 @@ int minimax(int depth, Game *b, float alpha, float beta) { } auto moves = GetSortedLegalMoves(b); if (moves.empty()) { - return quiescenceSearch(b, 0); + return EvaluateBoardForWhite(b); } bool shouldStore = true; - int bestEval = b->turn ? std::numeric_limits::lowest() - : std::numeric_limits::max(); + int bestScore = b->turn ? std::numeric_limits::lowest() + : std::numeric_limits::max(); if (b->turn) { for (Move move : moves) { @@ -236,9 +231,9 @@ int minimax(int depth, Game *b, float alpha, float beta) { int eval = minimax(depth - 1, b, alpha, beta); UnMakeMove(undo, b); - bestEval = std::max(bestEval, eval); + bestScore = std::max(bestScore, eval); - alpha = std::max(alpha, static_cast(bestEval)); + alpha = std::max(alpha, static_cast(bestScore)); if (alpha >= beta) { shouldStore = false; @@ -252,9 +247,9 @@ int minimax(int depth, Game *b, float alpha, float beta) { int eval = minimax(depth - 1, b, alpha, beta); UnMakeMove(undo, b); - bestEval = std::min(bestEval, eval); + bestScore = std::min(bestScore, eval); - beta = std::min(beta, static_cast(bestEval)); + beta = std::min(beta, static_cast(bestScore)); if (alpha >= beta) { shouldStore = false; break; // *snips* @@ -264,9 +259,9 @@ int minimax(int depth, Game *b, float alpha, float beta) { if (shouldStore) { b->Transpositions->operator[](gameHash) = {.depth = depth, - .Eval = bestEval}; + .Eval = bestScore}; } - return bestEval; + return bestScore; } static int PSTIndex(const int square, const bool white) { diff --git a/src/bot.hpp b/src/bot.hpp index 0796299..a8375e1 100644 --- a/src/bot.hpp +++ b/src/bot.hpp @@ -9,5 +9,5 @@ int EvaluateBoardForWhite(Game *b); int minimax(int depth, Game *b, float alpha, float beta); int ScoreMove(const Game *board, const Move &move); -std::vector GetSortedLegalMoves(Game *g); +std::vector GetSortedLegalMoves(Game *g, bool generateQuietMoves = true); #endif /* SRC_BOT_H_ */ diff --git a/src/moves.cpp b/src/moves.cpp index 4deafe3..c4cda26 100644 --- a/src/moves.cpp +++ b/src/moves.cpp @@ -8,7 +8,8 @@ #include "board/board.hpp" #include "moves.hpp" -void GenerateKnightMoves(Game *b, int from, std::vector &moves) { +void GenerateKnightMoves(Game *b, int from, std::vector &moves, + bool GenerateQuietMoves) { Piece knight = b->pieces[from]; if (knight.type != KNIGHT) { assert(false && "Calling generate knight moves on non knight"); @@ -32,10 +33,14 @@ void GenerateKnightMoves(Game *b, int from, std::vector &moves) { }; } + if (!GenerateQuietMoves && b->pieces[next].type == NONEPIECE) { + continue; + } moves.push_back({IndexToPosition(from), IndexToPosition(next)}); } }; -void GeneratePawnMoves(Game *b, int from, std::vector &moves) { +void GeneratePawnMoves(Game *b, int from, std::vector &moves, + bool quietMoves) { Piece pawn = b->pieces[from]; if (pawn.type != PAWN) { assert(false && "Calling generate pawn moves on non pawn"); @@ -52,24 +57,27 @@ void GeneratePawnMoves(Game *b, int from, std::vector &moves) { } // if piece it want to move to is none and it as legal move - if (b->pieces[next].type == NONEPIECE) { - if (position.rank + (pawn.color ? -1 : 1) == 0 || - position.rank + (pawn.color ? -1 : 1) == 7) { - moves.push_back({position, IndexToPosition(next), QUEEN}); - moves.push_back({position, IndexToPosition(next), ROOK}); - moves.push_back({position, IndexToPosition(next), BISHOP}); - moves.push_back({position, IndexToPosition(next), KNIGHT}); - } else { - moves.push_back({position, IndexToPosition(next)}); - } + if (quietMoves) { + if (b->pieces[next].type == NONEPIECE) { + if (position.rank + (pawn.color ? -1 : 1) == 0 || + position.rank + (pawn.color ? -1 : 1) == 7) { + moves.push_back({position, IndexToPosition(next), QUEEN}); + moves.push_back({position, IndexToPosition(next), ROOK}); + moves.push_back({position, IndexToPosition(next), BISHOP}); + moves.push_back({position, IndexToPosition(next), KNIGHT}); + } else { + moves.push_back({position, IndexToPosition(next)}); + } - int startingRank = pawn.color ? 6 : 1; - int twoSteps = from + step * 2; - if (position.rank == startingRank && - b->pieces[twoSteps].type == NONEPIECE) { - moves.push_back({position, IndexToPosition(twoSteps)}); + int startingRank = pawn.color ? 6 : 1; + int twoSteps = from + step * 2; + if (position.rank == startingRank && + b->pieces[twoSteps].type == NONEPIECE) { + moves.push_back({position, IndexToPosition(twoSteps)}); + } } - } + }; + for (int fileOffset : {-1, 1}) { int targetFile = position.file + fileOffset; int targetRank = position.rank + (pawn.color ? -1 : 1); @@ -99,9 +107,40 @@ void GeneratePawnMoves(Game *b, int from, std::vector &moves) { } } // the end -} +}; +void GenerateKingMoves(Game *b, int from, std::vector &moves, + bool GenerateQuietMoves) { + if (b->pieces[from].type != KING) { + assert(false && "calling generate king moves on non king"); + return; + } + if (b->pieces[from].color != b->turn) { + assert(false && "calling generate king moves on king of opposite color"); + return; + } + constexpr std::array king_moves{-1, 1, 8, -8, -9, 9, -7, 7}; + for (int offset : king_moves) { + int next = from + offset; + if (next >= 64 || next < 0) { + continue; + } + if (std::abs((next % 8) - (from % 8)) > 1) { + continue; + }; + if (b->pieces[next].type != NONEPIECE) { + if (b->pieces[next].color == b->turn) { + continue; + }; + } + if (!GenerateQuietMoves && b->pieces[next].type == NONEPIECE) { + continue; + } + + moves.push_back({IndexToPosition(from), IndexToPosition(next)}); + } +}; -std::vector GetPseudoLegalMoves(Game *b) { +std::vector GetPseudoLegalMoves(Game *b, bool GenerateQuietMoves) { std::vector moves; moves.reserve(40); @@ -113,36 +152,35 @@ std::vector GetPseudoLegalMoves(Game *b) { if (piece.type == NONEPIECE) { continue; } - if (piece.color != b->turn) + if (piece.color != b->turn) { continue; - - // add support for knight and king later - - if (piece.type == PAWN) { - GeneratePawnMoves(b, i, moves); } + if (piece.type == KNIGHT) { - GenerateKnightMoves(b, i, moves); + GenerateKnightMoves(b, i, moves, GenerateQuietMoves); }; - if (piece.type == BISHOP) { - GenerateSlidingMoves(b, i, bishop_Moves, moves); - } if (piece.type == KING) { - GenerateKingMoves(b, i, moves); + GenerateKingMoves(b, i, moves, GenerateQuietMoves); }; + if (piece.type == BISHOP) { + GenerateSlidingMoves(b, i, bishop_Moves, moves, GenerateQuietMoves); + } if (piece.type == ROOK) { - GenerateSlidingMoves(b, i, rook_Moves, moves); + GenerateSlidingMoves(b, i, rook_Moves, moves, GenerateQuietMoves); } if (piece.type == QUEEN) { - GenerateSlidingMoves(b, i, rook_Moves, moves); - GenerateSlidingMoves(b, i, bishop_Moves, moves); + GenerateSlidingMoves(b, i, rook_Moves, moves, GenerateQuietMoves); + GenerateSlidingMoves(b, i, bishop_Moves, moves, GenerateQuietMoves); + } + if (piece.type == PAWN) { + GeneratePawnMoves(b, i, moves, GenerateQuietMoves); } }; return moves; } -std::vector GetLegalMoves(Game *g) { - std::vector moves = GetPseudoLegalMoves(g); +std::vector GetLegalMoves(Game *g, bool quietMove) { + std::vector moves = GetPseudoLegalMoves(g, quietMove); std::vector legalMoves; for (Move move : moves) { @@ -319,7 +357,7 @@ Position IndexToPosition(int i) { void GenerateSlidingMoves(Game *b, int from, const std::array &directions, - std::vector &moves) { + std::vector &moves, bool GenerateQuietMoves) { for (uint i = 0; i < directions.size(); i++) { int direction = directions[i]; @@ -337,13 +375,17 @@ void GenerateSlidingMoves(Game *b, int from, if (i2 >= 64 || i2 < 0) { break; } - if (b->pieces[i2].color == b->turn && b->pieces[i2].type != NONEPIECE) { - break; - } + if ((direction == 1 || direction == -1) && (i2 / 8 != (i2 - direction) / 8)) { break; } + if (b->pieces[i2].color == b->turn && b->pieces[i2].type != NONEPIECE) { + break; + } + if (!GenerateQuietMoves && b->pieces[i2].type == NONEPIECE) { + continue; + } moves.push_back({IndexToPosition(from), IndexToPosition(i2)}); if (b->pieces[i2].color != b->turn && b->pieces[i2].type != NONEPIECE) { break; @@ -351,31 +393,3 @@ void GenerateSlidingMoves(Game *b, int from, } }; }; - -void GenerateKingMoves(Game *b, int from, std::vector &moves) { - if (b->pieces[from].type != KING) { - assert(false && "calling generate king moves on non king"); - return; - } - if (b->pieces[from].color != b->turn) { - assert(false && "calling generate king moves on king of opposite color"); - return; - } - constexpr std::array king_moves{-1, 1, 8, -8, -9, 9, -7, 7}; - for (int offset : king_moves) { - int next = from + offset; - if (next >= 64 || next < 0) { - continue; - } - if (std::abs((next % 8) - (from % 8)) > 1) { - continue; - }; - if (b->pieces[next].type != NONEPIECE) { - if (b->pieces[next].color == b->turn) { - continue; - }; - } - - moves.push_back({IndexToPosition(from), IndexToPosition(next)}); - } -} diff --git a/src/moves.hpp b/src/moves.hpp index 32143f7..282cff8 100644 --- a/src/moves.hpp +++ b/src/moves.hpp @@ -4,15 +4,18 @@ #include "board/board.hpp" #include -std::vector GetLegalMoves(Game *g); -std::vector GetPseudoLegalMoves(Game *g); +std::vector GetLegalMoves(Game *g, bool GenerateQuietMoves = true); +std::vector GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves); Position IndexToPosition(int i); void GenerateSlidingMoves(Game *g, int from, const std::array &directions, - std::vector &moves); -void GenerateKingMoves(Game *g, int from, std::vector &moves); -void GenerateKnightMoves(Game *g, int from, std::vector &moves); -void GeneratePawnMoves(Game *g, int from, std::vector &moves); + std::vector &moves, bool GenerateQuietMoves); +void GenerateKingMoves(Game *g, int from, std::vector &moves, + bool GenerateQuietMoves); +void GenerateKnightMoves(Game *b, int from, std::vector &moves, + bool GenerateQuietMoves); +void GeneratePawnMoves(Game *b, int from, std::vector &moves, + bool GenerateQuietMoves); bool IsSquareAttacked(Game *g, Position square, bool byWhite); GameState GetNewGameState(Game *g); -- cgit v1.2.3