aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bot.cpp41
-rw-r--r--src/bot.hpp2
-rw-r--r--src/moves.cpp150
-rw-r--r--src/moves.hpp15
4 files changed, 110 insertions, 98 deletions
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 <vector>
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<Move> GetSortedLegalMoves(Game *g) {
- auto moves = GetLegalMoves(g);
+std::vector<Move> 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<Move> attackMoves;
- for (Move move : GetSortedLegalMoves(b)) {
- if (b->pieces[PositionToIndex(move.To)].type != NONEPIECE) {
- attackMoves.push_back(move);
- }
- };
+ std::vector<Move> attackMoves = GetSortedLegalMoves(b, false);
if (attackMoves.empty()) {
return standPat;
}
- int bestEval = b->turn ? std::numeric_limits<int>::lowest()
- : std::numeric_limits<int>::max();
+ int bestScore = b->turn ? std::numeric_limits<int>::lowest()
+ : std::numeric_limits<int>::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<int>::lowest()
- : std::numeric_limits<int>::max();
+ int bestScore = b->turn ? std::numeric_limits<int>::lowest()
+ : std::numeric_limits<int>::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<float>(bestEval));
+ alpha = std::max(alpha, static_cast<float>(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<float>(bestEval));
+ beta = std::min(beta, static_cast<float>(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<Move> GetSortedLegalMoves(Game *g);
+std::vector<Move> 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<Move> &moves) {
+void GenerateKnightMoves(Game *b, int from, std::vector<Move> &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<Move> &moves) {
};
}
+ if (!GenerateQuietMoves && b->pieces[next].type == NONEPIECE) {
+ continue;
+ }
moves.push_back({IndexToPosition(from), IndexToPosition(next)});
}
};
-void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves) {
+void GeneratePawnMoves(Game *b, int from, std::vector<Move> &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<Move> &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<Move> &moves) {
}
}
// the end
-}
+};
+void GenerateKingMoves(Game *b, int from, std::vector<Move> &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<int, 8> 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<Move> GetPseudoLegalMoves(Game *b) {
+std::vector<Move> GetPseudoLegalMoves(Game *b, bool GenerateQuietMoves) {
std::vector<Move> moves;
moves.reserve(40);
@@ -113,36 +152,35 @@ std::vector<Move> 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<Move> GetLegalMoves(Game *g) {
- std::vector<Move> moves = GetPseudoLegalMoves(g);
+std::vector<Move> GetLegalMoves(Game *g, bool quietMove) {
+ std::vector<Move> moves = GetPseudoLegalMoves(g, quietMove);
std::vector<Move> legalMoves;
for (Move move : moves) {
@@ -319,7 +357,7 @@ Position IndexToPosition(int i) {
void GenerateSlidingMoves(Game *b, int from,
const std::array<int, 4> &directions,
- std::vector<Move> &moves) {
+ std::vector<Move> &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<Move> &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<int, 8> 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 <vector>
-std::vector<Move> GetLegalMoves(Game *g);
-std::vector<Move> GetPseudoLegalMoves(Game *g);
+std::vector<Move> GetLegalMoves(Game *g, bool GenerateQuietMoves = true);
+std::vector<Move> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves);
Position IndexToPosition(int i);
void GenerateSlidingMoves(Game *g, int from,
const std::array<int, 4> &directions,
- std::vector<Move> &moves);
-void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves);
-void GenerateKnightMoves(Game *g, int from, std::vector<Move> &moves);
-void GeneratePawnMoves(Game *g, int from, std::vector<Move> &moves);
+ std::vector<Move> &moves, bool GenerateQuietMoves);
+void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
+ bool GenerateQuietMoves);
+void GenerateKnightMoves(Game *b, int from, std::vector<Move> &moves,
+ bool GenerateQuietMoves);
+void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves,
+ bool GenerateQuietMoves);
bool IsSquareAttacked(Game *g, Position square, bool byWhite);
GameState GetNewGameState(Game *g);