aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/moves.cpp180
-rw-r--r--src/uci.cpp240
-rw-r--r--src/uci.hpp1
3 files changed, 219 insertions, 202 deletions
diff --git a/src/moves.cpp b/src/moves.cpp
index a236536..b7b1688 100644
--- a/src/moves.cpp
+++ b/src/moves.cpp
@@ -38,7 +38,7 @@ constexpr std::array<std::uint64_t, 64> KNIGHT_ATTACKS = computeKnightAttacks();
static void GenerateKnightMoves(Game *b, std::vector<Move> &moves,
bool GenerateQuietMoves) {
-
+
uint64_t knights = b->PieceBitboards[b->turn][KNIGHT];
while (knights != 0) {
int from = __builtin_ctzll(knights);
@@ -83,24 +83,38 @@ 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 (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)});
- }
+ if (b->pieces[next].type == NONEPIECE && quietMoves) {
+ if (position.rank + (pawn.color ? 1 : -1) == 0 ||
+ position.rank + (pawn.color ? 1 : -1) == 7) {
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(next),
+ .promotion = QUEEN,
+ });
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(next),
+ .promotion = ROOK,
+ });
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(next),
+ .promotion = BISHOP,
+ });
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(next),
+ .promotion = KNIGHT,
+ });
+ } else {
+ moves.push_back({.From = position, .To = IndexToPosition(next)});
+ }
- int startingRank = pawn.color ? 1 : 6;
- int twoSteps = from + step * 2;
- if (position.rank == startingRank &&
- b->pieces[twoSteps].type == NONEPIECE) {
- moves.push_back({position, IndexToPosition(twoSteps)});
- }
+ int startingRank = pawn.color ? 1 : 6;
+ int twoSteps = from + (step * 2);
+ if (position.rank == startingRank &&
+ b->pieces[twoSteps].type == NONEPIECE) {
+ moves.push_back({position, IndexToPosition(twoSteps)});
}
};
@@ -108,39 +122,51 @@ void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves,
int targetFile = position.file + fileOffset;
int targetRank = position.rank + (pawn.color ? 1 : -1);
- if (targetFile < 0 || targetFile >= 8)
- continue;
-
- if (targetRank < 0 || targetRank >= 8)
+ if (targetFile < 0 || targetFile >= 8) {
continue;
+ }
- int target = targetRank * 8 + targetFile;
+ int target = (targetRank * 8) + targetFile;
if (IndexToPosition(target) == b->enPassant && b->canEnpassant) {
- moves.push_back({position, IndexToPosition(target)});
+ moves.push_back({.From = position, .To = IndexToPosition(target)});
}
if (b->pieces[target].type != NONEPIECE &&
b->pieces[target].color != pawn.color) {
if (targetRank == 0 || targetRank == 7) {
- moves.push_back({position, IndexToPosition(target), QUEEN});
- moves.push_back({position, IndexToPosition(target), ROOK});
- moves.push_back({position, IndexToPosition(target), BISHOP});
- moves.push_back({position, IndexToPosition(target), KNIGHT});
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(target),
+ .promotion = QUEEN,
+ });
+ moves.push_back({.From = position,
+ .To = IndexToPosition(target),
+ .promotion = ROOK});
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(target),
+ .promotion = BISHOP,
+ });
+ moves.push_back({
+ .From = position,
+ .To = IndexToPosition(target),
+ .promotion = KNIGHT,
+ });
} else {
- moves.push_back({position, IndexToPosition(target)});
+ moves.push_back({.From = position, .To = IndexToPosition(target)});
+ moves.push_back({.From = position, .To = IndexToPosition(target)});
}
}
}
- // the end
};
-void GenerateKingMoves(Game *b, int from, std::vector<Move> &moves,
+void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
bool GenerateQuietMoves) {
- if (b->pieces[from].type != KING) {
+ if (g->pieces[from].type != KING) {
assert(false && "calling generate king moves on non king");
return;
}
- if (b->pieces[from].color != b->turn) {
+ if (g->pieces[from].color != g->turn) {
assert(false && "calling generate king moves on king of opposite color");
return;
}
@@ -153,12 +179,12 @@ void GenerateKingMoves(Game *b, int from, std::vector<Move> &moves,
if (std::abs((next % 8) - (from % 8)) > 1) {
continue;
};
- if (b->pieces[next].type != NONEPIECE) {
- if (b->pieces[next].color == b->turn) {
+ if (g->pieces[next].type != NONEPIECE) {
+ if (g->pieces[next].color == g->turn) {
continue;
};
}
- if (!GenerateQuietMoves && b->pieces[next].type == NONEPIECE) {
+ if (!GenerateQuietMoves && g->pieces[next].type == NONEPIECE) {
continue;
}
@@ -166,44 +192,44 @@ void GenerateKingMoves(Game *b, int from, std::vector<Move> &moves,
}
};
-std::vector<Move> GetPseudoLegalMoves(Game *b, bool GenerateQuietMoves) {
+std::vector<Move> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves) {
std::vector<Move> moves;
moves.reserve(40);
- GenerateKnightMoves(b, moves, GenerateQuietMoves);
+ GenerateKnightMoves(g, moves, GenerateQuietMoves);
constexpr std::array<int, 4> rook_Moves{-1, 1, 8, -8};
constexpr std::array<int, 4> bishop_Moves{-9, 9, -7, 7};
- uint64_t piece_bitboard = b->PieceBitboard;
+ uint64_t piece_bitboard = g->PieceBitboard;
while (piece_bitboard != 0) {
int i = __builtin_ctzll(piece_bitboard);
piece_bitboard &= piece_bitboard - 1;
- Piece piece = b->pieces[i];
+ Piece piece = g->pieces[i];
if (piece.type == NONEPIECE) {
assert(false && "got none piece in piece bitboard");
}
- if (piece.color != b->turn) {
+ if (piece.color != g->turn) {
continue;
}
if (piece.type == PAWN) {
- GeneratePawnMoves(b, i, moves, GenerateQuietMoves);
+ GeneratePawnMoves(g, i, moves, GenerateQuietMoves);
}
if (piece.type == BISHOP) {
- GenerateSlidingMoves(b, i, bishop_Moves, moves, GenerateQuietMoves);
+ GenerateSlidingMoves(g, i, bishop_Moves, moves, GenerateQuietMoves);
}
if (piece.type == ROOK) {
- GenerateSlidingMoves(b, i, rook_Moves, moves, GenerateQuietMoves);
+ GenerateSlidingMoves(g, i, rook_Moves, moves, GenerateQuietMoves);
}
if (piece.type == QUEEN) {
- GenerateSlidingMoves(b, i, rook_Moves, moves, GenerateQuietMoves);
- GenerateSlidingMoves(b, i, bishop_Moves, moves, GenerateQuietMoves);
+ GenerateSlidingMoves(g, i, rook_Moves, moves, GenerateQuietMoves);
+ GenerateSlidingMoves(g, i, bishop_Moves, moves, GenerateQuietMoves);
}
if (piece.type == KING) {
- GenerateKingMoves(b, i, moves, GenerateQuietMoves);
+ GenerateKingMoves(g, i, moves, GenerateQuietMoves);
if (GenerateQuietMoves) {
- GenerateCastlingMoves(i, b, moves);
+ GenerateCastlingMoves(i, g, moves);
}
};
};
@@ -356,9 +382,9 @@ GameState GetNewGameState(Game *g) {
}
Position IndexToPosition(int i) {
- uint8_t rank = static_cast<uint8_t>(i / 8); // 0-7
- uint8_t file = static_cast<uint8_t>(i % 8); // 0-7
- return {rank, file};
+ auto rank = static_cast<uint8_t>(i / 8); // 0-7
+ auto file = static_cast<uint8_t>(i % 8); // 0-7
+ return {.rank = rank, .file = file};
}
void GenerateSlidingMoves(Game *b, int from,
@@ -375,8 +401,9 @@ void GenerateSlidingMoves(Game *b, int from,
if (direction == 7 || direction == -7 || direction == 9 ||
direction == -9) {
- if (std::abs(newFile - oldFile) != 1)
+ if (std::abs(newFile - oldFile) != 1) {
break;
+ }
}
if (i2 >= 64 || i2 < 0) {
break;
@@ -392,7 +419,8 @@ void GenerateSlidingMoves(Game *b, int from,
if (!GenerateQuietMoves && b->pieces[i2].type == NONEPIECE) {
continue;
}
- moves.push_back({IndexToPosition(from), IndexToPosition(i2)});
+ moves.push_back(
+ {.From = IndexToPosition(from), .To = IndexToPosition(i2)});
if (b->pieces[i2].color != b->turn && b->pieces[i2].type != NONEPIECE) {
break;
}
@@ -412,11 +440,11 @@ void GenerateCastlingMoves(int from, Game *g, std::vector<Move> &moves) {
if (from != 4 && g->turn) {
return;
}
- bool oneToRight = g->PieceBitboard & (1ULL << (from + 1));
- bool twoToRight = g->PieceBitboard & (1ULL << (from + 2));
- bool oneToLeft = g->PieceBitboard & (1ULL << (from - 1));
- bool twoToLeft = g->PieceBitboard & (1ULL << (from - 2));
- bool threeToLeft = g->PieceBitboard & (1ULL << (from - 3));
+ bool oneToRight = (g->PieceBitboard & (1ULL << (from + 1))) > 0;
+ bool twoToRight = (g->PieceBitboard & (1ULL << (from + 2))) > 0;
+ bool oneToLeft = (g->PieceBitboard & (1ULL << (from - 1))) > 0;
+ bool twoToLeft = (g->PieceBitboard & (1ULL << (from - 2))) > 0;
+ bool threeToLeft = (g->PieceBitboard & (1ULL << (from - 3))) > 0;
Position kingPosition = FindKing(g, g->turn);
@@ -426,36 +454,30 @@ void GenerateCastlingMoves(int from, Game *g, std::vector<Move> &moves) {
}
auto pathIsSafe = [&](int step) {
return !IsSquareAttacked(g, IndexToPosition(from + step), !g->turn) &&
- !IsSquareAttacked(g, IndexToPosition(from + 2 * step), !g->turn);
+ !IsSquareAttacked(g, IndexToPosition(from + (2 * step)), !g->turn);
};
if (g->turn) {
// white
- if (!oneToRight && !twoToRight && g->whiteCastleKing) {
- if (pathIsSafe(1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
- }
+ if (!oneToRight && !twoToRight && g->whiteCastleKing && pathIsSafe(1)) {
+ moves.push_back(
+ {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
}
- if (!oneToLeft && !twoToLeft && !threeToLeft && g->whiteCastleQueen) {
- if (pathIsSafe(-1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
- }
+ if (!oneToLeft && !twoToLeft && !threeToLeft && g->whiteCastleQueen &&
+ pathIsSafe(-1)) {
+ moves.push_back(
+ {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
}
}
if (!g->turn) {
// black
- if (!oneToRight && !twoToRight && g->blackCastleKing) {
- if (pathIsSafe(1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
- }
+ if (!oneToRight && !twoToRight && g->blackCastleKing && pathIsSafe(1)) {
+ moves.push_back(
+ {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
}
- if (!oneToLeft && !twoToLeft && !threeToLeft && g->blackCastleQueen) {
- if (pathIsSafe(-1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
- }
+ if (!oneToLeft && !twoToLeft && !threeToLeft && g->blackCastleQueen &&
+ pathIsSafe(-1)) {
+ moves.push_back(
+ {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
}
}
}
diff --git a/src/uci.cpp b/src/uci.cpp
index 23fe123..cc5ae18 100644
--- a/src/uci.cpp
+++ b/src/uci.cpp
@@ -1,6 +1,8 @@
+#include <array>
#include <cassert>
#include <cctype>
#include <chrono>
+#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <fstream>
@@ -23,24 +25,7 @@
static const std::string starting_fen =
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
-std::ofstream uciLog("cache/uci_log.txt", std::ios::app);
-
-void LogUci(const std::string &message) {
- if (!uciLog.is_open()) {
- return;
- }
-
- auto now = std::chrono::system_clock::now();
- auto time = std::chrono::system_clock::to_time_t(now);
-
- uciLog << "[" << std::put_time(std::localtime(&time), "%H:%M:%S") << "] "
- << message << "\n";
-
- uciLog.flush();
-}
-using namespace std;
-
-Move UciToMove(const string &uci) {
+Move UciToMove(const std::string &uci) {
Position from;
Position to;
PieceType promotion = NONEPIECE;
@@ -71,7 +56,7 @@ Move UciToMove(const string &uci) {
break;
default:
assert(false && "Unexpected promotion type");
- cout << "Unexpected promotion type";
+ std::cout << "Unexpected promotion type";
exit(1);
}
}
@@ -115,7 +100,7 @@ static void PrintBitboard(uint64_t bb, const std::string &name) {
}
static void DebugBitboards(const Game *g) {
- static constexpr const char *pieceNames[] = {
+ static constexpr const std::array<std::string, 7> pieceNames = {
"None", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
};
@@ -135,7 +120,8 @@ static void DebugBitboards(const Game *g) {
std::cout << (color ? "White\n" : "Black\n");
for (int type = PAWN; type <= KING; ++type) {
- PrintBitboard(g->PieceBitboards[color][type], pieceNames[type]);
+ PrintBitboard(g->PieceBitboards[color][type],
+ pieceNames[static_cast<size_t>(type)]);
}
}
}
@@ -145,16 +131,16 @@ static void printPromotionLetter(PieceType p) {
}
switch (p) {
case QUEEN:
- cout << "q";
+ std::cout << "q";
break;
case ROOK:
- cout << "r";
+ std::cout << "r";
break;
case KNIGHT:
- cout << "n";
+ std::cout << "n";
break;
case BISHOP:
- cout << "b";
+ std::cout << "b";
break;
default:
assert(false && "Unexpected promotion type");
@@ -168,7 +154,7 @@ static void printBoard(Game *g) {
Piece piece = g->pieces[(rank * 8) + file];
if (piece.type == NONEPIECE) {
- print(" 00");
+ std::print(" 00");
continue;
};
std::print(" {0}{1}", static_cast<int>(piece.type),
@@ -178,14 +164,108 @@ static void printBoard(Game *g) {
std::print(" | {0}\n", rank + 1);
}
}
+static void GoCommand(Game *game, std::string &cmd) {
+ std::stringstream ss(cmd);
+
+ std::string token;
+ int depth = -1;
+
+ int wtime = -1;
+ int btime = -1;
+
+ int wncr = 0;
+ int bncr = 0;
+
+ ss >> token; // go
+
+ while (ss >> token) {
+ if (token == "depth") {
+ ss >> depth;
+ }
+ if (token == "wtime") {
+ ss >> wtime;
+ }
+ if (token == "btime") {
+ ss >> btime;
+ }
+ if (token == "incr") {
+ ss >> wncr;
+ bncr = wncr;
+ }
+ if (token == "winc") {
+ ss >> wncr;
+ }
+ if (token == "binc") {
+ ss >> bncr;
+ }
+ }
+
+ if (depth != -1 && depth <= 0) {
+ std::cout << "Fatal: Depth must be positive integer";
+ exit(1);
+ }
+ move_options options = {
+ .wtime = wtime,
+ .btime = btime,
+ .wncr = wncr,
+ .bncr = bncr,
+ };
+ Move best = GetBestMove(game, depth, options);
+
+ std::cout << "bestmove ";
+ std::cout << static_cast<char>(best.From.file + 'a') << 1 + best.From.rank
+ << static_cast<char>(best.To.file + 'a') << 1 + best.To.rank;
+
+ printPromotionLetter(best.promotion);
+
+ std::cout << "\n";
+ std::cout.flush();
+}
+static void positionCommnad(Game *game, std::string &cmd) {
+ std::stringstream ss(cmd);
+ std::string token;
+
+ ss >> token; // position
+
+ ss >> token;
+
+ if (token == "startpos") {
+ *game = initBoard(starting_fen, game->Transpositions);
+ } else if (token == "fen") {
+ std::string fen;
+ std::string part;
+
+ // FEN has spaces, need 6 parts
+ for (int i = 0; i < 6; i++) {
+ ss >> part;
+ if (i != 0) {
+ fen += ' ';
+ }
+ fen += part;
+ }
+
+ *game = initBoard(fen, game->Transpositions);
+ }
+
+ // check for moves
+ while (ss >> token) {
+ if (token == "moves") {
+ break;
+ }
+ }
+
+ while (ss >> token) {
+ Move move = UciToMove(token);
+
+ MakeMove(move, game);
+ }
+}
void Uci() {
- unordered_map<uint64_t, TranspositionsEntry> transpositions = {};
+ std::unordered_map<uint64_t, TranspositionsEntry> transpositions = {};
Game game = initBoard(starting_fen, &transpositions);
- string cmd;
-
- while (getline(cin, cmd)) {
- LogUci("GUI -> ENGINE: " + cmd);
+ std::string cmd;
+ while (getline(std::cin, cmd)) {
if (cmd == "quit") {
return;
}
@@ -196,9 +276,9 @@ void Uci() {
DebugBitboards(&game);
}
if (cmd == "uci") {
- cout << "id name " << engine_info();
- cout << "uciok\n";
- cout.flush();
+ std::cout << "id name " << engine_info();
+ std::cout << "uciok\n";
+ std::cout.flush();
}
if (cmd == "ucinewgame") {
game =
@@ -206,98 +286,14 @@ void Uci() {
&transpositions);
}
if (cmd == "isready") {
- cout << "readyok\n";
- cout.flush();
+ std::cout << "readyok\n";
+ std::cout.flush();
}
if (cmd.starts_with("go")) {
- stringstream ss(cmd);
-
- string token;
- int depth = -1;
-
- int wtime = -1;
- int btime = -1;
-
- int wncr = 0;
- int bncr = 0;
-
- ss >> token; // go
-
- while (ss >> token) {
- if (token == "depth") {
- ss >> depth;
- }
- if (token == "wtime") {
- ss >> wtime;
- }
- if (token == "btime") {
- ss >> btime;
- }
- if (token == "incr") {
- ss >> wncr;
- bncr = wncr;
- }
- }
-
- if (depth != -1 && depth <= 0) {
- cout << "Fatal: Depth must be positive integer";
- exit(1);
- }
- move_options options = {
- .wtime = wtime,
- .btime = btime,
- .wncr = wncr,
- .bncr = bncr,
- };
- Move best = GetBestMove(&game, depth, options);
-
- cout << "bestmove ";
- cout << static_cast<char>(best.From.file + 'a') << 1 + best.From.rank
- << static_cast<char>(best.To.file + 'a') << 1 + best.To.rank;
-
- printPromotionLetter(best.promotion);
-
- cout << "\n";
- cout.flush();
+ GoCommand(&game, cmd);
}
if (cmd.starts_with("position")) {
- stringstream ss(cmd);
- string token;
-
- ss >> token; // position
-
- ss >> token;
-
- if (token == "startpos") {
- game = initBoard(starting_fen, &transpositions);
- } else if (token == "fen") {
- string fen;
- string part;
-
- // FEN has spaces, need 6 parts
- for (int i = 0; i < 6; i++) {
- ss >> part;
- if (i != 0) {
- fen += " ";
- }
- fen += part;
- }
-
- game = initBoard(fen, &transpositions);
- }
-
- // check for moves
- while (ss >> token) {
- if (token == "moves") {
- break;
- }
- }
-
- while (ss >> token) {
- Move move = UciToMove(token);
-
- MakeMove(move, &game);
- }
+ positionCommnad(&game, cmd);
}
}
}
diff --git a/src/uci.hpp b/src/uci.hpp
index 8160442..19fd021 100644
--- a/src/uci.hpp
+++ b/src/uci.hpp
@@ -6,7 +6,6 @@
#include <unordered_map>
Move UciToMove(const std::string &uci);
-void LogUci(const std::string &message);
void Uci();
Game initBoard(
const std::string &startingFEN,