aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <adammegarules1@gmail.com>2026-08-15 17:01:54 +0200
committerAdam <adammegarules1@gmail.com>2026-08-15 17:01:54 +0200
commit4eb36e67eca586a662298bfe8cc5392fbfa698e0 (patch)
tree6c232d59d1566377fbaeec035f4f799618f63421
parentc1d6113da12bfbe92ae718d93dd56e25556e52cb (diff)
implementing memory optimazied move using uint16_t instead of a four integers and one byte
-rw-r--r--src/board/board.cpp120
-rw-r--r--src/board/board.hpp18
-rw-r--r--src/bot.cpp76
-rw-r--r--src/bot.hpp3
-rw-r--r--src/moves.cpp144
-rw-r--r--src/moves.hpp14
-rw-r--r--src/uci.cpp24
-rw-r--r--src/uci.hpp3
8 files changed, 213 insertions, 189 deletions
diff --git a/src/board/board.cpp b/src/board/board.cpp
index 3b1383a..a533b63 100644
--- a/src/board/board.cpp
+++ b/src/board/board.cpp
@@ -88,14 +88,18 @@ uint8_t getToValueFromMove(uint16_t move) { return (move >> 8) & 63; };
Position FindKing(Game *g, bool color) {
return IndexToPosition(__builtin_ctzll(g->PieceBitboards[color][KING]));
}
-UndoMove MakeMove(Move move, Game *g) {
+UndoMove MakeMove(uint16_t move, Game *g) {
+ uint8_t fromSquare = getFromValueFromMove(move);
+ uint8_t toSquare = getToValueFromMove(move);
+ PieceType promotion = getPromotionTypeFromMove(move);
+
UndoMove undo = {};
- undo.from = move.From;
- undo.to = move.To;
+ undo.from = fromSquare;
+ undo.to = toSquare;
- undo.movedPiece = g->pieces[PositionToIndex(move.From)];
- undo.capturedPiece = g->pieces[PositionToIndex(move.To)];
+ undo.movedPiece = g->pieces[fromSquare];
+ undo.capturedPiece = g->pieces[toSquare];
undo.oldTurn = g->turn;
undo.oldCanEnpassant = g->canEnpassant;
@@ -112,8 +116,8 @@ UndoMove MakeMove(Move move, Game *g) {
undo.OldBlackCastleQueen = g->blackCastleQueen;
// play move
- Piece piece = g->pieces[PositionToIndex(move.From)];
- Piece piece2 = g->pieces[PositionToIndex(move.To)];
+ Piece piece = g->pieces[fromSquare];
+ Piece piece2 = g->pieces[toSquare];
if (piece2.type != NONEPIECE) {
if (piece2.color == g->turn) {
@@ -130,8 +134,9 @@ UndoMove MakeMove(Move move, Game *g) {
}
// Playing enpasstant
- if (piece.type == PAWN && g->canEnpassant && move.To == g->enPassant) {
- Position capturedPawn = move.To;
+ if (piece.type == PAWN && g->canEnpassant &&
+ IndexToPosition(toSquare) == g->enPassant) {
+ Position capturedPawn = IndexToPosition(toSquare);
capturedPawn.rank += piece.color ? -1 : 1;
undo.wasEnPassantCapture = true;
@@ -157,33 +162,37 @@ UndoMove MakeMove(Move move, Game *g) {
// Adding enpassant
if (piece.type == PAWN) {
- Position to = move.To;
- to.rank -= piece.color ? 2 : -2;
- if (to == move.From) {
+ int to = toSquare;
+ // check if a pawn has moved two squares
+ to -= piece.color ? 2 * 8 : -2 * 8;
+ if (to == fromSquare) {
g->canEnpassant = true;
- Position target = move.From;
- target.rank += piece.color ? 1 : -1;
- g->enPassant = target;
+ int target = fromSquare;
+ target += piece.color ? 8 : -8;
+ g->enPassant = IndexToPosition(target);
};
}
- // Promotions
- if (piece.type == PAWN && move.To.rank == (piece.color ? 7 : 0)) {
- piece.type = move.promotion == NONEPIECE ? QUEEN : move.promotion;
+ // promotion is always set and should only be aplied when reached final rank
+ // (default: knight)
+ if (piece.type == PAWN &&
+ IndexToPosition(toSquare).rank == (piece.color ? 7 : 0)) {
+ piece.type = promotion;
}
// caslte
- if (piece.type == KING && move.From.rank == (piece.color ? 0 : 7) &&
- std::abs(move.To.file - move.From.file) == 2) {
+ if (piece.type == KING &&
+ IndexToPosition(fromSquare).rank == (piece.color ? 0 : 7) &&
+ std::abs(toSquare - fromSquare) == 2) {
undo.wasCastle = true;
- undo.CastledSide = move.To.file > move.From.file;
+ undo.CastledSide = toSquare > fromSquare;
if (undo.CastledSide) {
- Position rookFrom = move.From;
+ Position rookFrom = IndexToPosition(fromSquare);
rookFrom.file = 7;
- Position rookTo = move.From;
+ Position rookTo = IndexToPosition(toSquare);
rookTo.file = 5;
uint64_t from = 1ULL << PositionToIndex(rookFrom);
@@ -203,10 +212,10 @@ UndoMove MakeMove(Move move, Game *g) {
g->pieces[PositionToIndex(rookFrom)] = {false, NONEPIECE};
} else {
// Queenside: a -> d
- Position rookFrom = move.From;
+ Position rookFrom = IndexToPosition(fromSquare);
rookFrom.file = 0;
- Position rookTo = move.From;
+ Position rookTo = IndexToPosition(toSquare);
rookTo.file = 3;
uint64_t from = 1ULL << PositionToIndex(rookFrom);
@@ -241,20 +250,21 @@ UndoMove MakeMove(Move move, Game *g) {
}
}
+ // if rook has moved
if (piece.type == ROOK) {
- if (piece.color) { // White
- if (move.From.rank == 0 && move.From.file == 0) { // a1
+ if (piece.color) { // White
+ if (fromSquare == 0) { // a1
g->whiteCastleQueen = false;
}
- if (move.From.rank == 0 && move.From.file == 7) { // h1
+ if (fromSquare == 7) { // h1
g->whiteCastleKing = false;
}
- } else { // Black
- if (move.From.rank == 7 && move.From.file == 0) { // a8
+ } else { // Black
+ if (fromSquare == 7 * 8) { // a8
g->blackCastleQueen = false;
}
- if (move.From.rank == 7 && move.From.file == 7) { // h8
+ if (fromSquare == 7 * 9) { // h8
g->blackCastleKing = false;
}
}
@@ -262,24 +272,28 @@ UndoMove MakeMove(Move move, Game *g) {
// this part is written with ai
if (piece2.type == ROOK) {
- if (piece2.color) { // White rook captured
- if (move.To.rank == 0 && move.To.file == 0) // a1
+ if (piece2.color) { // White rook captured
+ if (toSquare == 0) { // a1
g->whiteCastleQueen = false;
-
- if (move.To.rank == 0 && move.To.file == 7) // h1
+ }
+ if (toSquare == 7) { // h1
g->whiteCastleKing = false;
- } else { // Black rook captured
- if (move.To.rank == 7 && move.To.file == 0) // a8
+ }
+ } else { // Black rook captured
+ if (toSquare == 7 * 8) { // a8
g->blackCastleQueen = false;
+ }
- if (move.To.rank == 7 && move.To.file == 7) // h8
+ if (toSquare == 7 * 9) {
+ // h8
g->blackCastleKing = false;
+ }
}
}
// playing the moves
- uint64_t from = 1ULL << PositionToIndex(move.From);
- uint64_t to = 1ULL << PositionToIndex(move.To);
+ uint64_t from = 1ULL << fromSquare;
+ uint64_t to = 1ULL << toSquare;
// remove moving piece from source
g->PieceBitboards[piece.color][undo.movedPiece.type] ^= from;
@@ -297,14 +311,15 @@ UndoMove MakeMove(Move move, Game *g) {
// add moving piece to destination
g->PieceBitboards[piece.color][piece.type] ^= to;
- if (piece.color)
+ if (piece.color) {
g->WhitePieceBitboard ^= from | to;
- else
+ } else {
g->BlackPieceBitboard ^= from | to;
+ }
g->PieceBitboard = g->WhitePieceBitboard | g->BlackPieceBitboard;
- g->pieces[PositionToIndex(move.To)] = piece;
- g->pieces[PositionToIndex(move.From)] = {false, NONEPIECE};
+ g->pieces[toSquare] = piece;
+ g->pieces[fromSquare] = {.color = false, .type = NONEPIECE};
// changing who turn it is
g->turn = !g->turn;
@@ -326,9 +341,9 @@ UndoMove MakeMove(Move move, Game *g) {
return undo;
};
void UnMakeMove(UndoMove undo, Game *g) {
- g->pieces[PositionToIndex(undo.from)] = undo.movedPiece;
+ g->pieces[undo.from] = undo.movedPiece;
- g->pieces[PositionToIndex(undo.to)] = undo.capturedPiece;
+ g->pieces[undo.to] = undo.capturedPiece;
if (undo.wasEnPassantCapture) {
g->pieces[PositionToIndex(undo.enPassantCapturedSquare)] =
@@ -353,10 +368,10 @@ void UnMakeMove(UndoMove undo, Game *g) {
if (undo.wasCastle) {
if (undo.CastledSide) {
// f -> h
- Position rookFrom = undo.from;
+ Position rookFrom = IndexToPosition(undo.from);
rookFrom.file = 5;
- Position rookTo = undo.from;
+ Position rookTo = IndexToPosition(undo.from);
rookTo.file = 7;
g->pieces[PositionToIndex(rookTo)] = g->pieces[PositionToIndex(rookFrom)];
@@ -366,14 +381,17 @@ void UnMakeMove(UndoMove undo, Game *g) {
};
} else {
// d -> a
- Position rookFrom = undo.from;
+ Position rookFrom = IndexToPosition(undo.from);
rookFrom.file = 3;
- Position rookTo = undo.from;
+ Position rookTo = IndexToPosition(undo.from);
rookTo.file = 0;
g->pieces[PositionToIndex(rookTo)] = g->pieces[PositionToIndex(rookFrom)];
- g->pieces[PositionToIndex(rookFrom)] = {false, NONEPIECE};
+ g->pieces[PositionToIndex(rookFrom)] = {
+ .color = false,
+ .type = NONEPIECE,
+ };
}
}
diff --git a/src/board/board.hpp b/src/board/board.hpp
index b27a9d1..b24811c 100644
--- a/src/board/board.hpp
+++ b/src/board/board.hpp
@@ -43,23 +43,13 @@ PieceType getPromotionTypeFromMove(uint16_t move);
uint8_t getFromValueFromMove(uint16_t move);
uint8_t getToValueFromMove(uint16_t move);
-struct Move {
- Position From;
- Position To;
-
- PieceType promotion = NONEPIECE;
- bool operator==(const Move &other) const {
- return From == other.From && To == other.To && promotion == other.promotion;
- }
-};
-
enum Flag : std::uint8_t { EXACT, LOWERBOUND, UPPERBOUND };
struct TranspositionsEntry {
int depth = -1;
int Eval = 0;
Flag flag = EXACT;
- Move bestMove = {};
+ uint16_t bestMove = {};
};
struct Game {
Piece pieces[64];
@@ -85,8 +75,8 @@ struct UndoMove {
Piece movedPiece;
Piece capturedPiece;
- Position from;
- Position to;
+ uint8_t from;
+ uint8_t to;
bool wasEnPassantCapture = false;
Position enPassantCapturedSquare;
@@ -112,7 +102,7 @@ struct UndoMove {
};
int PositionToIndex(Position i);
-UndoMove MakeMove(Move move, Game *g);
+UndoMove MakeMove(uint16_t move, Game *g);
void UnMakeMove(UndoMove undo, Game *g);
Position FindKing(Game *g, bool color);
diff --git a/src/bot.cpp b/src/bot.cpp
index 5db3939..43a76f4 100644
--- a/src/bot.cpp
+++ b/src/bot.cpp
@@ -1,9 +1,3 @@
-#include "bot.hpp"
-#include "board/board.hpp"
-#include "evaluate.hpp"
-#include "moves.hpp"
-#include "zobrist.hpp"
-
#include <algorithm>
#include <array>
#include <cassert>
@@ -16,6 +10,12 @@
#include <ratio>
#include <vector>
+#include "board/board.hpp"
+#include "bot.hpp"
+#include "evaluate.hpp"
+#include "moves.hpp"
+#include "zobrist.hpp"
+
constexpr int MAXIMUM_DEPTH = 10;
constexpr int MAXIMUM_TIME_PER_MOVE = 7;
constexpr int Q_DEPTH_LIMIT = 4;
@@ -33,8 +33,12 @@ double timeToThingMS = -1;
std::chrono::time_point<std::chrono::steady_clock> searchStartTime;
bool searchStopped = false;
-static int ScoreMove(const Game *board, const Move &move,
- const Move *bestMove) {
+static int ScoreMove(const Game *board, const uint16_t &move,
+ const uint16_t *bestMove) {
+ uint8_t from = getFromValueFromMove(move);
+ uint8_t to = getToValueFromMove(move);
+ PieceType promotion = getPromotionTypeFromMove(move);
+
// Indexed by PieceType (NONE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING).
static constexpr std::array<int, 7> PIECE_VALUES = {
0, // NONEPIECE
@@ -54,8 +58,8 @@ static int ScoreMove(const Game *board, const Move &move,
score += 1000000;
}
- const Piece moving = board->pieces[PositionToIndex(move.From)];
- const Piece captured = board->pieces[PositionToIndex(move.To)];
+ const Piece moving = board->pieces[from];
+ const Piece captured = board->pieces[to];
// MVV-LVA: value the capture by what we win, penalise by what we spend.
if (captured.type != NONEPIECE) {
@@ -64,21 +68,27 @@ static int ScoreMove(const Game *board, const Move &move,
score -= PIECE_VALUES[moving.type];
}
- if (move.promotion != NONEPIECE) {
- score += 8000;
+ // promotion bonus
+ if (IndexToPosition(to).rank == (board->turn ? 7 : 0)) {
+ if (promotion == QUEEN) {
+ score += 8000;
+ }
+ score += 3000;
}
- if (move.To.rank == (board->turn ? 6 : 1) && moving.type == PAWN) {
+ if (IndexToPosition(to).rank == (board->turn ? 6 : 1) &&
+ moving.type == PAWN) {
score += 8000;
}
return score;
}
-static std::vector<Move> GetSortedLegalMoves(Game *g, bool generateQuietMoves,
- const Move *bestMove) {
+static std::vector<uint16_t> GetSortedLegalMoves(Game *g,
+ bool generateQuietMoves,
+ const uint16_t *bestMove) {
auto moves = GetLegalMoves(g, generateQuietMoves);
- std::ranges::sort(moves, [&](const Move &a, const Move &c) {
+ std::ranges::sort(moves, [&](const uint16_t &a, const uint16_t &c) {
return ScoreMove(g, a, bestMove) > ScoreMove(g, c, bestMove);
});
return moves;
@@ -112,7 +122,7 @@ static int quiescenceSearch(Game *b, int qdepth, int alpha, int beta, int ply) {
auto moves = GetSortedLegalMoves(b, false, nullptr);
- for (Move move : moves) {
+ for (uint16_t move : moves) {
UndoMove undo = MakeMove(move, b);
int score = -quiescenceSearch(b, qdepth + 1, -beta, -alpha, ply + 1);
@@ -127,16 +137,16 @@ static int quiescenceSearch(Game *b, int qdepth, int alpha, int beta, int ply) {
return alpha;
};
static int search(int depth, Game *b, int alpha, int beta, int ply) {
+ if (timeToThingMS == -1) {
+ assert(false && "Expected set time: internal error");
+ exit(1);
+ }
Nodes++;
if ((Nodes & 2047) == 0) {
double elapsedMiliseconds =
std::chrono::duration<double, std::milli>(
std::chrono::steady_clock::now() - searchStartTime)
.count();
- if (timeToThingMS == -1) {
- assert(false && "Expected set time");
- exit(1);
- }
if (elapsedMiliseconds >= timeToThingMS) {
searchStopped = true;
return 0;
@@ -173,22 +183,21 @@ static int search(int depth, Game *b, int alpha, int beta, int ply) {
return quiescenceSearch(b, 0, alpha, beta, ply);
}
- Move ttBestMove = entry != nullptr ? entry->bestMove : Move{};
- std::vector<Move> moves = GetSortedLegalMoves(b, true, &ttBestMove);
+ uint16_t ttBestMove = entry != nullptr ? entry->bestMove : uint16_t{};
+ std::vector<uint16_t> moves = GetSortedLegalMoves(b, true, &ttBestMove);
if (moves.empty()) {
- const Position king = FindKing(b, b->turn);
- if (IsSquareAttacked(b, king, !b->turn)) {
+ if (IsSquareAttacked(b, FindKing(b, b->turn), !b->turn)) {
return -(MATE - ply); // mated
}
return 0; // stalemate
}
- Move bestMove = moves[0];
+ uint16_t bestMove = moves[0];
const int alphaOrig = alpha;
int bestScore = -INF;
- for (Move move : moves) {
+ for (uint16_t move : moves) {
UndoMove undo = MakeMove(move, b);
int score = -search(depth - 1, b, -beta, -alpha, ply + 1);
@@ -221,14 +230,15 @@ static int search(int depth, Game *b, int alpha, int beta, int ply) {
}
struct SearchResult {
- Move bestMove;
+ uint16_t bestMove;
int score;
};
// Searches every root move to `depth` plies and returns the best one.
// `previousBest` is the best move from the previous iteration (used for move
// ordering, the core win of iterative deepening).
-static SearchResult SearchDepth(Game *b, int depth, const Move *previousBest) {
+static SearchResult SearchDepth(Game *b, int depth,
+ const uint16_t *previousBest) {
auto moves = GetSortedLegalMoves(b, true, previousBest);
if (moves.empty()) {
@@ -238,12 +248,12 @@ static SearchResult SearchDepth(Game *b, int depth, const Move *previousBest) {
};
}
- Move bestMove = moves[0];
+ uint16_t bestMove = moves[0];
int bestEval = -INF;
int alpha = -INF;
int beta = INF;
- for (Move move : moves) {
+ for (uint16_t move : moves) {
UndoMove undo = MakeMove(move, b);
int eval = -search(depth - 1, b, -beta, -alpha, 1);
@@ -278,7 +288,7 @@ static void PrintInfo(const int depth, const int engineScore,
}
}
-Move GetBestMove(Game *b, int maxDepth, move_options options) {
+uint16_t GetBestMove(Game *b, int maxDepth, move_options options) {
searchStopped = false;
Nodes = 0;
@@ -290,7 +300,7 @@ Move GetBestMove(Game *b, int maxDepth, move_options options) {
return {};
}
- Move bestMove = legalMoves[0];
+ uint16_t bestMove = legalMoves[0];
searchStartTime = std::chrono::steady_clock::now();
diff --git a/src/bot.hpp b/src/bot.hpp
index 9f97e2c..907554d 100644
--- a/src/bot.hpp
+++ b/src/bot.hpp
@@ -2,6 +2,7 @@
#define SRC_BOT_H_
#include "board/board.hpp"
+#include <cstdint>
struct move_options {
int wtime;
@@ -10,6 +11,6 @@ struct move_options {
int bncr;
};
-Move GetBestMove(Game *b, int depth, move_options options);
+uint16_t GetBestMove(Game *b, int depth, move_options options);
#endif /* SRC_BOT_H_ */
diff --git a/src/moves.cpp b/src/moves.cpp
index 812e734..a80f4c7 100644
--- a/src/moves.cpp
+++ b/src/moves.cpp
@@ -36,16 +36,16 @@ constexpr std::array<std::uint64_t, 64> computeKnightAttacks() {
constexpr std::array<std::uint64_t, 64> KNIGHT_ATTACKS = computeKnightAttacks();
-static void GenerateKnightMoves(Game *b, std::vector<Move> &moves,
+static void GenerateKnightMoves(Game *b, std::vector<uint16_t> &moves,
bool GenerateQuietMoves) {
uint64_t knights = b->PieceBitboards[b->turn][KNIGHT];
while (knights != 0) {
- int from = __builtin_ctzll(knights);
+ uint8_t from = static_cast<uint8_t>(__builtin_ctzll(knights));
knights &= knights - 1;
uint64_t knight_attacks = KNIGHT_ATTACKS[static_cast<size_t>(from)];
while (knight_attacks != 0) {
- int next = __builtin_ctzll(knight_attacks);
+ uint8_t next = static_cast<uint8_t>(__builtin_ctzll(knight_attacks));
knight_attacks &= knight_attacks - 1;
bool hasFriendlyPiece =
@@ -59,13 +59,12 @@ static void GenerateKnightMoves(Game *b, std::vector<Move> &moves,
if (!GenerateQuietMoves && !isCaptuare) {
continue;
}
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(next)});
+ moves.push_back(CreateMove(from, next));
}
}
};
-void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves,
+void GeneratePawnMoves(Game *b, uint8_t from, std::vector<uint16_t> &moves,
bool quietMoves) {
Piece pawn = b->pieces[from];
if (pawn.type != PAWN) {
@@ -86,80 +85,73 @@ void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves,
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,
- });
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)),
+ static_cast<uint8_t>(next), QUEEN));
+
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)),
+ static_cast<uint8_t>(next), ROOK));
+
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)),
+ static_cast<uint8_t>(next), BISHOP));
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)),
+ static_cast<uint8_t>(next), KNIGHT));
} else {
- moves.push_back({.From = position, .To = IndexToPosition(next)});
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)),
+ static_cast<uint8_t>(next)));
}
int startingRank = pawn.color ? 1 : 6;
- int twoSteps = from + (step * 2);
+ uint8_t twoSteps = static_cast<uint8_t>(from + (step * 2));
if (position.rank == startingRank &&
b->pieces[twoSteps].type == NONEPIECE) {
- moves.push_back({.From = position, .To = IndexToPosition(twoSteps)});
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), twoSteps));
}
};
for (int fileOffset : {-1, 1}) {
- int targetFile = position.file + fileOffset;
- int targetRank = position.rank + (pawn.color ? 1 : -1);
+ uint8_t targetFile = static_cast<uint8_t>(position.file + fileOffset);
+ uint8_t targetRank =
+ static_cast<uint8_t>(position.rank + (pawn.color ? 1 : -1));
- if (targetFile < 0 || targetFile >= 8) {
+ if (targetFile >= 8) {
+ continue;
+ }
+ if (targetRank >= 8) {
continue;
}
- int target = (targetRank * 8) + targetFile;
+ uint8_t target = static_cast<uint8_t>((targetRank * 8)) + targetFile;
if (IndexToPosition(target) == b->enPassant && b->canEnpassant) {
- moves.push_back({.From = position, .To = IndexToPosition(target)});
+ moves.push_back(
+ CreateMove(static_cast<uint8_t>(PositionToIndex(position)), target));
}
if (b->pieces[target].type != NONEPIECE &&
b->pieces[target].color != pawn.color) {
if (targetRank == 0 || targetRank == 7) {
- 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,
- });
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), target, QUEEN));
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), target, ROOK));
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), target, BISHOP));
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), target, KNIGHT));
} else {
- moves.push_back({.From = position, .To = IndexToPosition(target)});
+ moves.push_back(CreateMove(
+ static_cast<uint8_t>(PositionToIndex(position)), target));
}
}
}
};
-void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
+void GenerateKingMoves(Game *g, int from, std::vector<uint16_t> &moves,
bool GenerateQuietMoves) {
if (g->pieces[from].type != KING) {
assert(false && "calling generate king moves on non king");
@@ -171,8 +163,8 @@ void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
}
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) {
+ uint8_t next = static_cast<uint8_t>(from + offset);
+ if (next >= 64) {
continue;
}
if (std::abs((next % 8) - (from % 8)) > 1) {
@@ -187,13 +179,12 @@ void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
continue;
}
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(next)});
+ moves.push_back(CreateMove(static_cast<uint8_t>(from), next));
}
};
-std::vector<Move> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves) {
- std::vector<Move> moves;
+std::vector<uint16_t> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves) {
+ std::vector<uint16_t> moves;
moves.reserve(40);
GenerateKnightMoves(g, moves, GenerateQuietMoves);
@@ -203,7 +194,7 @@ std::vector<Move> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves) {
uint64_t piece_bitboard = g->PieceBitboard;
while (piece_bitboard != 0) {
- int i = __builtin_ctzll(piece_bitboard);
+ uint8_t i = static_cast<uint8_t>(__builtin_ctzll(piece_bitboard));
piece_bitboard &= piece_bitboard - 1;
Piece piece = g->pieces[i];
if (piece.type == NONEPIECE) {
@@ -331,12 +322,12 @@ bool IsSquareAttacked(Game *g, Position square, bool byColor) {
return false;
}
-std::vector<Move> GetLegalMoves(Game *g, bool quietMove) {
- std::vector<Move> moves = GetPseudoLegalMoves(g, quietMove);
- std::vector<Move> legalMoves;
+std::vector<uint16_t> GetLegalMoves(Game *g, bool quietMove) {
+ std::vector<uint16_t> moves = GetPseudoLegalMoves(g, quietMove);
+ std::vector<uint16_t> legalMoves;
legalMoves.reserve(moves.size());
- for (const Move &move : moves) {
+ for (const uint16_t &move : moves) {
UndoMove undo = MakeMove(move, g);
bool legal = true;
@@ -390,7 +381,8 @@ Position IndexToPosition(int i) {
void GenerateSlidingMoves(Game *b, int from,
const std::array<int, 4> &directions,
- std::vector<Move> &moves, bool GenerateQuietMoves) {
+ std::vector<uint16_t> &moves,
+ bool GenerateQuietMoves) {
for (uint i = 0; i < directions.size(); i++) {
int direction = directions[i];
@@ -421,14 +413,14 @@ void GenerateSlidingMoves(Game *b, int from,
continue;
}
moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(i2)});
+ CreateMove(static_cast<uint8_t>(from), static_cast<uint8_t>(i2)));
if (b->pieces[i2].color != b->turn && b->pieces[i2].type != NONEPIECE) {
break;
}
}
};
};
-void GenerateCastlingMoves(int from, Game *g, std::vector<Move> &moves) {
+void GenerateCastlingMoves(int from, Game *g, std::vector<uint16_t> &moves) {
Piece piece = g->pieces[from];
if (piece.type != KING) {
assert(false && "Calling generate castling moves on non king piece");
@@ -460,25 +452,25 @@ void GenerateCastlingMoves(int from, Game *g, std::vector<Move> &moves) {
if (g->turn) {
// white
if (!oneToRight && !twoToRight && g->whiteCastleKing && pathIsSafe(1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
+ moves.push_back(CreateMove(static_cast<uint8_t>(from),
+ static_cast<uint8_t>(from + 2)));
}
if (!oneToLeft && !twoToLeft && !threeToLeft && g->whiteCastleQueen &&
pathIsSafe(-1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
+ moves.push_back(CreateMove(static_cast<uint8_t>(from),
+ static_cast<uint8_t>(from - 2)));
}
}
if (!g->turn) {
// black
if (!oneToRight && !twoToRight && g->blackCastleKing && pathIsSafe(1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from + 2)});
+ moves.push_back(CreateMove(static_cast<uint8_t>(from),
+ static_cast<uint8_t>(from + 2)));
}
if (!oneToLeft && !twoToLeft && !threeToLeft && g->blackCastleQueen &&
pathIsSafe(-1)) {
- moves.push_back(
- {.From = IndexToPosition(from), .To = IndexToPosition(from - 2)});
+ moves.push_back(CreateMove(static_cast<uint8_t>(from),
+ static_cast<uint8_t>(from - 2)));
}
}
}
diff --git a/src/moves.hpp b/src/moves.hpp
index 57d1467..54ab730 100644
--- a/src/moves.hpp
+++ b/src/moves.hpp
@@ -2,20 +2,22 @@
#define SRC_MOVES_H_
#include "board/board.hpp"
+#include <cstdint>
#include <vector>
-std::vector<Move> GetLegalMoves(Game *g, bool GenerateQuietMoves = true);
-std::vector<Move> GetPseudoLegalMoves(Game *g, bool GenerateQuietMoves);
+std::vector<uint16_t> GetLegalMoves(Game *g, bool GenerateQuietMoves = true);
+std::vector<uint16_t> 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, bool GenerateQuietMoves);
-void GenerateKingMoves(Game *g, int from, std::vector<Move> &moves,
+ std::vector<uint16_t> &moves,
+ bool GenerateQuietMoves);
+void GenerateKingMoves(Game *g, int from, std::vector<uint16_t> &moves,
bool GenerateQuietMoves);
-void GeneratePawnMoves(Game *b, int from, std::vector<Move> &moves,
+void GeneratePawnMoves(Game *b, uint8_t from, std::vector<uint16_t> &moves,
bool GenerateQuietMoves);
bool IsSquareAttacked(Game *g, Position square, bool byColor);
-void GenerateCastlingMoves(int from, Game *g, std::vector<Move> &moves);
+void GenerateCastlingMoves(int from, Game *g, std::vector<uint16_t> &moves);
GameState GetNewGameState(Game *g);
#endif /* SRC_MOVES_H_ */
diff --git a/src/uci.cpp b/src/uci.cpp
index 0266aa6..92c7072 100644
--- a/src/uci.cpp
+++ b/src/uci.cpp
@@ -22,7 +22,7 @@
static const std::string starting_fen =
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
-Move UciToMove(const std::string &uci) {
+uint16_t UciToMove(const std::string &uci) {
Position from;
Position to;
PieceType promotion = NONEPIECE;
@@ -32,6 +32,7 @@ Move UciToMove(const std::string &uci) {
std::cout << "expected valid uci string\n";
exit(1);
}
+ // TODO: validate before using
from.file = static_cast<uint8_t>(uci[0] - 'a');
from.rank = static_cast<uint8_t>(uci[1] - '1');
@@ -58,7 +59,8 @@ Move UciToMove(const std::string &uci) {
}
}
- return {.From = from, .To = to, .promotion = promotion};
+ return CreateMove(static_cast<uint8_t>(PositionToIndex(from)),
+ static_cast<uint8_t>(PositionToIndex(to)), promotion);
}
Game initBoard(
@@ -207,13 +209,21 @@ static void GoCommand(Game *game, std::string &cmd) {
.wncr = wncr,
.bncr = bncr,
};
- Move best = GetBestMove(game, depth, options);
+ uint16_t best = GetBestMove(game, depth, options);
+
+ Piece piece = game->pieces[getFromValueFromMove(best)];
+
+ Position from = IndexToPosition(getFromValueFromMove(best));
+ Position to = IndexToPosition(getToValueFromMove(best));
+ PieceType promotion = getPromotionTypeFromMove(best);
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;
+ std::cout << static_cast<char>(from.file + 'a') << 1 + from.rank
+ << static_cast<char>(to.file + 'a') << 1 + to.rank;
- printPromotionLetter(best.promotion);
+ if ((to.rank == 0 || to.rank == 7) && piece.type == PAWN) {
+ printPromotionLetter(promotion);
+ }
std::cout << "\n";
std::cout.flush();
@@ -252,7 +262,7 @@ static void positionCommnad(Game *game, std::string &cmd) {
}
while (ss >> token) {
- Move move = UciToMove(token);
+ uint16_t move = UciToMove(token);
MakeMove(move, game);
}
diff --git a/src/uci.hpp b/src/uci.hpp
index 19fd021..ba2a56c 100644
--- a/src/uci.hpp
+++ b/src/uci.hpp
@@ -2,10 +2,11 @@
#define SRC_UCI_H_
#include "board/board.hpp"
+#include <cstdint>
#include <string>
#include <unordered_map>
-Move UciToMove(const std::string &uci);
+uint16_t UciToMove(const std::string &uci);
void Uci();
Game initBoard(
const std::string &startingFEN,