This is a recreation of niklasf's 'python-chess' in C++
All credit for the original code and algorithms go to niklasf and his credits
His source code can be found here: https://github.com/niklasf/python-chess
cpp-chess is a chess library for C++, with move generation, move validation, and support for common formats. This is the Scholar's mate in cpp-chess:
>>> #include "chess.cpp"
>>> #include <iostream>
>>> chess::Board board;
>>> std::cout << board.legal_moves(); // doctest: +ELLIPSIS
<LegalMoveGenerator at ... (Nh3, Nf3, Nc3, Na3, h3, g3, f3, e3, d3, c3, ...)>
>>> chess::LegalMoveGenerator legal_moves = board.legal_moves();
>>> std::cout << (std::find(std::begin(legal_moves), std::end(legal_moves), chess::Move::from_uci("a8a1")) != std::end(legal_moves));
0
>>> std::cout << board.push_san("e4");
Move::from_uci("e2e4")
>>> std::cout << board.push_san("e5");
Move::from_uci("e7e5")
>>> std::cout << board.push_san("Qh5");
Move::from_uci("d1h5")
>>> std::cout << board.push_san("Nc6");
Move::from_uci("b8c6")
>>> std::cout << board.push_san("Bc4");
Move::from_uci("f1c4")
>>> std::cout << board.push_san("Nf6");
Move::from_uci("g8f6")
>>> std::cout << board.push_san("Qxf7");
Move::from_uci("h5f7")
>>> std::cout << board.is_checkmate();
1
>>> std::cout << board;
Board("r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4")
-
Supports C++ 20+.
-
Make and unmake moves.
>>> chess::Move Nf3 = chess::Move::from_uci("g1f3"); >>> board.push(Nf3); // Make the move >>> std::cout << board.pop(); // Unmake the last move Move::from_uci("g1f3")
-
Show a simple ASCII board.
>>> chess::Board board = chess::Board("r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4"); >>> std::cout << std::string(board); r . b q k b . r p p p p . Q p p . . n . . n . . . . . . p . . . . . B . P . . . . . . . . . . . P P P P . P P P R N B . K . N R
-
Detects checkmates, stalemates and draws by insufficient material.
>>> std::cout << board.is_stalemate(); 0 >>> std::cout << board.is_insufficient_material(); 0 >>> std::cout << *board.outcome(); Outcome(termination=Termination::CHECKMATE, winner=true)
-
Detects repetitions. Has a half-move clock.
>>> std::cout << board.can_claim_threefold_repetition(); 0 >>> std::cout << board.halfmove_clock; 0 >>> std::cout << board.can_claim_fifty_moves(); 0 >>> std::cout << board.can_claim_draw(); 0
With the new rules from July 2014, a game ends as a draw (even without a claim) once a fivefold repetition occurs or if there are 75 moves without a pawn push or capture. Other ways of ending a game take precedence.
>>> std::cout << board.is_fivefold_repetition(); 0 >>> std::cout << board.is_seventyfive_moves(); 0
-
Detects checks and attacks.
>>> std::cout << board.is_check(); 1 >>> std::cout << board.is_attacked_by(chess::WHITE, chess::E8); 1 >>> chess::SquareSet attackers = board.attackers(chess::WHITE, chess::F3); >>> std::cout << attackers; SquareSet(0x0000'0000'0000'4040) >>> std::cout << (std::find(std::begin(attackers), std::end(attackers), chess::G2) != std::end(attackers)); 1 >>> std::cout << std::string(attackers); . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . 1 .
-
Parses and creates SAN representation of moves.
>>> chess::Board board; >>> std::cout << board.san(chess::Move(chess::E2, chess::E4)); e4 >>> std::cout << board.parse_san("Nf3"); Move::from_uci("g1f3") >>> std::cout << board.variation_san({chess::Move::from_uci("e2e4"), chess::Move::from_uci("e7e5"), chess::Move::from_uci("g1f3")}); 1. e4 e5 2. Nf3
-
Parses and creates FENs, extended FENs and Shredder FENs.
>>> std::cout << board.fen(); rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 >>> std::cout << board.shredder_fen(); rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1 >>> chess::Board board = chess::Board("8/8/8/2k5/4K3/8/8/8 w - - 4 45"); >>> std::cout << board.piece_at(chess::C5); Piece::from_symbol('k')
-
Parses and creates EPDs.
>>> chess::Board board; >>> std::cout << board.epd(false, "legal", std::nullopt, {{"bm", board.parse_uci("d2d4")}}); rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - bm d4; >>> auto ops = board.set_epd("1k1r4/pp1b1R2/3q2pp/4p3/2B5/4Q3/PPP2B2/2K5 b - - bm Qd1+; id \"BK.01\";"); >>> std::cout << (std::get<std::vector<chess::Move>>(ops.at("bm")) == std::vector({chess::Move::from_uci("d6d1")}) && std::get<std::string>(ops.at("id")) == "BK.01"); 1