My issue is that in some positions, my perft reports the correct number of total nodes, but incorrect stats. Some example output:
Code: Select all
Running perft depth 4...
90:
90: Wrote JSON results to /Users/benvining/Documents/libchess/Builds/ninja/tests/perft/results/start_pos/depth_4.json
90:
90: a2a3 8457
90: b2b3 9345
90: c2c3 9272
90: d2d3 11959
90: e2e3 13134
90: f2f3 8457
90: g2g3 9345
90: h2h3 8457
90: a2a4 9329
90: b2b4 9332
90: c2c4 9744
90: d2d4 12435
90: e2e4 13160
90: f2f4 8929
90: g2g4 9328
90: h2h4 9329
90: b1a3 8885
90: b1c3 9755
90: g1f3 9748
90: g1h3 8881
90:
90: Nodes: 197281
90: Captures: 1610
90: En passant captures: 0
90: Castles: 0
90: Promotions: 0
90: Checks: 481
90: Checkmates: 8
90: Stalemates: 0
90:
90: Search time: 1s
90: ERROR: Expected 1576 captures, got 1610
90: ERROR: Expected 469 checks, got 481
Code: Select all
struct PerftResult final {
size_t nodes { 0uz };
size_t captures { 0uz };
size_t enPassantCaptures { 0uz };
size_t castles { 0uz };
size_t promotions { 0uz };
size_t checks { 0uz };
size_t checkmates { 0uz };
size_t stalemates { 0uz };
std::vector<std::pair<Move, size_t>> rootNodes;
constexpr PerftResult& operator+=(const PerftResult& rhs) noexcept;
};
template <bool IsRoot>
constexpr PerftResult perft(const size_t depth, const Position& startingPosition) // NOLINT(misc-no-recursion)
{
if (depth == 0uz)
return { .nodes = 1uz };
PerftResult result;
for (const auto& move : generate(startingPosition)) {
if (startingPosition.is_capture(move)) {
++result.captures;
if (startingPosition.is_en_passant(move))
++result.enPassantCaptures;
}
if (move.is_castling())
++result.castles;
if (move.promotedType.has_value())
++result.promotions;
const auto newPosition = game::after_move(startingPosition, move);
const bool isCheck = newPosition.is_check();
if (isCheck)
++result.checks;
if (! any_legal_moves(newPosition)) {
if (isCheck)
++result.checkmates;
else
++result.stalemates;
}
const auto childResult = perft<false>(depth - 1uz, newPosition);
if constexpr (IsRoot) {
result.rootNodes.emplace_back(move, childResult.nodes);
}
result += childResult;
}
return result;
}