Chess engine in cpp
Chess engines are cool
Chess.com even uses them too!
You can make one yourself like I did myself
It's okay if you did it bad,you are just a beginner
Well I'm not
So my chess engine may be good but it's okay if yours is not
I am about to give you a source code of ONE OF MY CHESS ENGINES
It's coded in cpp
Source code is below
typedef uint64_t U64;
const U64 FILE_A = 0x8080808080808080ULL;
const U64 RANK_5 = 0xff00000000ULL;
#define set_bit(b, i) ((b) |= (1ULL << i))
#define get_bit(b, i) ((b) & (1ULL << i))
#define clear_bit(b, i) ((b) &= ~(1ULL << i))
#define get_LSB(b) (__builtin_ctzll(b))
inline int pop_LSB(U64 &b) {
int i = get_LSB(b);
b &= b - 1;
return i;
}
constexpr U64 west(U64 b) { return (b & ~FILE_A) << 1; }
constexpr U64 east(U64 b) { return (b & ~FILE_H) >> 1; }
constexpr U64 north_west(U64 b) { return (b & ~FILE_A) << 9; }
constexpr U64 north_east(U64 b) { return (b & ~FILE_H) << 7; }
// ... etc
U64 attacks, knights = 0ULL;
// place knight on board
set_bit(knights, square);
// add attacks
attacks = (((knights >> 6) | (knights << 10)) & ~FILE_GH) |
(((knights >> 10) | (knights << 6)) & ~FILE_AB) |
(((knights >> 15) | (knights << 17)) & ~FILE_H) |
(((knights >> 17) | (knights << 15)) & ~FILE_A);
U64 attacks = KING_ATTACKS[from] & targets;
// only look at the pawns on the 7th rank
U64 promotions = (bitboards[P] & RANK_7)
// promote north if the square is empty
U64 north_promotions = north(promotions) & empties;
// promote west/east if there is an enemy piece there that we may capture
U64 west_promotions = north_west(promotions) & blacks;
U64 east_promotions = north_east(promotions) & blacks;
U64 ROOK_ATTACKS[64][4096];
U64 Board::getRookAttacks(int square, U64 blockers) const {
return ROOK_ATTACKS[square][getRookKey(blockers, square)];
}
Board::MoveVec Board::generateMoves<LEGAL>(MoveVec &moves) const {
// if the king is in check then the legal moves can only be evasions
isKingInCheck(boardTurn) ? generateMoves<EVASIONS>(moves) : generateMoves<PSEUDO_LEGAL>(moves);
// extract legal moves from pseudo-legal moves
std::vector<Move> legal_moves;
legal_moves.reserve(MOVES_RESERVE_SIZE);
for (auto &move: moves) {
if (isMoveLegal(move)) legal_moves.push_back(move);
}
return legal_moves;
}
MoveVec &moves;
generateQueenMoves(moves, friendly_queens, ~friendlies);
void Board::generateQueenMoves(MoveVec &moves, U64 queens, U64 targets) const {
// for each of our queens
while (queens) {
// get the position of the queen
int from = pop_LSB(queens);
// get the (pre-calculated) attacks of the queen
// we limit the attacks to contain enemy squares (captures) and
// empty squares (regular moves), moving to a friendly square is not possible
U64 attacks = getQueenAttacks(from, all) & targets;
// add a move for each attack
while (attacks) addMove(Move(getSquare(from), getSquare(pop_LSB(attacks))), moves);
}
}
// promotion-eligible pawns are on rank 7
U64 promotions = pawns & RANK_7;
U64 non_promotions = pawns & ~RANK_7;
// pawns can be pushed if there is an empty space
U64 singles = north(non_promotions) & empties;
U64 doubles = north(singles & RANK_3) & empties;
if (promotions) {
// north promotions are regular pushes and need an empty square
U64 north_promotions = north(promotions) & empties;
// west/east promotions can only be captures
U64 west_promotions = north_west(promotions) & blacks;
U64 east_promotions = north_east(promotions) & blacks;
}
// captures can happen left/right and need an enemy piece
U64 west_captures = north_west(non_promotions) & blacks;
U64 east_captures = north_east(non_promotions) & blacks;
if (enpassant) {
U64 enpassants = non_promotions & PAWN_ATTACKS[0][get_LSB(enpassant)];
}
if (turn == WHITE && hasCastlingRights(CastlingRights::WhiteKingside)) {
if (!get_bit(all, f1) && !get_bit(all, g1) &&
!isSquareAttackedBy(e1, BLACK) &&
!isSquareAttackedBy(f1, BLACK))
addMove(Move(Square::E1, Square::G1), moves);
}
uint64_t perft(Board &board, int depth) {
std::vector<Move> moves;
moves.reserve(MOVES_RESERVE_SIZE);
moves = board.generateMoves<LEGAL>(moves);
uint64_t nodes = 0;
if (depth == 1) return moves.size();
for (const auto &move: moves) {
Position position = board.copyBoard(board);
board.makeMove(move);
nodes += perft(board, depth - 1);
board.restorePosition(board, position);
}
return nodes;
}
const int PIECE_SCORES_MATERIAL[6] = {
// pawn, knight, bishop, rook, queen, king
100, 300, 300, 500, 900, 12000
};
const int KNIGHT_SCORES_POSITIONAL[64] = {
// a score for each square on the board
-58, -38, -13, -28, -31, -27, -63, -99,
-25, -8, -25, -2, -9, -25, -24, -52,
-24, -20, 10, 9, -1, -9, -19, -41,
-17, 3, 22, 22, 22, 11, 8, -18,
-18, -6, 16, 25, 16, 17, 4, -18,
-23, -3, -1, 15, 10, -3, -20, -22,
-42, -20, -10, -5, -2, -20, -23, -44,
-29, -51, -23, -15, -22, -18, -50, -64,
};
for (auto &move: moves) {
int score = 0;
// capture moves (10010 - 10055)
if (captured.has_value()) {
score = 10000 + MVV_LVA[moved.value().toInt() - 6 * (moved.value().toInt() >= 6)][captured.value().toInt()
- 6 * (captured.value().toInt() >= 6)];
}
// promotion moves (9300 - 9900)
if (promotion.has_value()) {
score = 9000 + PIECE_SCORES[static_cast<int>(promotion.value())];
}
move.setScore(score);
}
Now that is my chess engine source code learn a coding language and code a chess engine (only if you want to).
my first brilliant